2017-10-13 4 views
-1

En Python 3.6, j'ai une liste comme celle ci-dessous et je n'arrive pas à comprendre comment rechercher correctement les valeurs. Donc, si on me donne la chaîne de recherche ci-dessous, je dois rechercher les valeurs du titre et des balises et celle qui correspond le mieux, je retournerais l'identifiant et s'il y avait beaucoup d'images différentes (ids) avec le même montant des matches, alors celui dont le titre vient en premier par ordre alphabétique serait retourné. En outre, il est supposé ne pas être sensible à la casse. Donc, dans le code, j'ai la recherche en tant que mon terme à rechercher et il devrait retourner la première valeur d'identification, mais retourne plutôt des valeurs différentes.Comment rechercher dans une liste imbriquée avec un dictionnaire en Python?

image_info = [ 
{ 
    "id" : "34694102243_3370955cf9_z", 
    "title" : "Eastern", 
    "flickr_user" : "Sean Davis", 
    "tags" : ["Los Angeles", "California", "building"] 
}, 
{ 
    "id" : "37198655640_b64940bd52_z", 
    "title" : "Spreetunnel", 
    "flickr_user" : "Jens-Olaf Walter", 
    "tags" : ["Berlin", "Germany", "tunnel", "ceiling"] 
}, 
{ 
    "id" : "34944112220_de5c2684e7_z", 
    "title" : "View from our rental", 
    "flickr_user" : "Doug Finney", 
    "tags" : ["Mexico", "ocean", "beach", "palm"] 
}, 
{ 
    "id" : "36140096743_df8ef41874_z", 
    "title" : "Someday", 
    "flickr_user" : "Thomas Hawk", 
    "tags" : ["Los Angeles", "Hollywood", "California", "Volkswagen", "Beatle", "car"] 
} 

]

my_counter = 0 
search = "CAT IN BUILding" 
search = search.lower().split() 
matches = {} 

for image in image_info: 
    for word in search: 
     word = word.lower() 
     if word in image["title"].lower().split(" "): 
      my_counter += 1 
      print(my_counter) 
     if word in image["tags"]: 
      my_counter +=1 
      print(my_counter) 
    if my_counter > 0: 
     matches[image["id"]] = my_counter 
     my_counter = 0 
+0

Que voulez-vous dire quand vous dites « retour »? Vous ne retournez rien? Quel est exactement votre résultat attendu, et en quoi diffère-t-il de ce que vous avez? Pouvez-vous être plus explicite? –

+0

J'ai couru votre code et il m'a donné le premier ID à l'intérieur des matchs dict. Cependant, il y a un bug avec les tags. Vous mettez en minuscule les mots dans la chaîne de recherche et non dans les étiquettes, mais les étiquettes contiennent des mots en majuscules. Vous ne serez pas en mesure de faire correspondre Los Angeles par exemple. – bouma

+0

@ juanpa.arrivillaga Donc, j'utilise le terme de recherche "CAT IN BUILding" pour faire une recherche parmi les valeurs du titre et des balises dans la liste/dictionnaire, et je veux que la fonction retourne le nombre de correspondances trouvées. Donc, pour "CAT IN BUILding" il devrait retourner 1 et l'ID de l'endroit où il a trouvé le match à 34694102243_3370955cf9_z. Si le terme de recherche était "construire au Mexique plage", il devrait renvoyer 34944112220_de5c2684e7_z car il y avait 2 correspondances dans les tags. – Gray

Répondre

0

Cette variante de code où j'ai essayé d'effectuer une pré-indexer les données avant de faire la recherche. Cette mise en œuvre d'une très rudimentaire de la façon dont CloudSearch ou ElasticSearch indexerait et recherche

import itertools 
from collections import Counter 
image_info = [ 
{ 
    "id" : "34694102243_3370955cf9_z", 
    "title" : "Eastern", 
    "flickr_user" : "Sean Davis", 
    "tags" : ["Los Angeles", "California", "building"] 
}, 
{ 
    "id" : "37198655640_b64940bd52_z", 
    "title" : "Spreetunnel", 
    "flickr_user" : "Jens-Olaf Walter", 
    "tags" : ["Berlin", "Germany", "tunnel", "ceiling"] 
}, 
{ 
    "id" : "34944112220_de5c2684e7_z", 
    "title" : "View from our rental", 
    "flickr_user" : "Doug Finney", 
    "tags" : ["Mexico", "ocean", "beach", "palm"] 
}, 
{ 
    "id" : "36140096743_df8ef41874_z", 
    "title" : "Someday", 
    "flickr_user" : "Thomas Hawk", 
    "tags" : ["Los Angeles", "Hollywood", "California", "Volkswagen", "Beatle", "car"] 
} 
] 

my_counter = 0 
search = "CAT IN BUILding california" 
search = set(search.lower().split()) 
matches = {} 

index = {} 


# Building a rudimentary search index 
for info in image_info: 
    bag = info["title"].lower().split(" ") 
    tags = [t.lower().split(" ") for t in info["tags"]] # we want to be able to hit "los angeles" as will as "los" and "angeles" 
    tags = list(itertools.chain.from_iterable(tags)) 
    for k in (bag + tags): 
     if k in index: 
      index[k].append(info["id"]) 
     else: 
      index[k] = [info["id"]] 

#print(index) 

hits = [] 

for s in search: 
    if s in index: 
     hits += index[s] 
print(Counter(hits).most_common(1)[0][0]) 
+0

Si j'essaye d'exécuter le code que vous avez fourni, j'obtiens l'erreur: TypeError: append() prend exactement un argument (3 donnés). – Gray

+0

Merci @Mahi. J'ai changé le code pour résoudre le problème. – djinn

+0

Merci, cela a fonctionné. Mais, j'ai une question. À l'heure actuelle, il affiche tous les identifiants d'image et la quantité de hits qu'il contient, mais comment l'obtenir pour imprimer uniquement l'identifiant de l'image pour celui avec le plus grand nombre de hits au lieu de tous ceux qui ont eu des hits? – Gray

0

Vous créez une nouvelle entrée dans les matches de dictionnaire [image [ "id"]] = my_counter. Si vous voulez conserver seulement 1 entrée dans le dictionnaire pour ce terme de recherche et que vous voulez voir image_id et compter. J'ai modifié votre dict et votre condition. J'espère que cela aide.

my_counter = 0 
search_term = "CAT IN BUILding" 
search = search_term.lower().split() 
matches = {} 
matches[search_term] = {} 

for image in image_info: 
    for word in search: 
     word = word.lower() 
     if word in image["title"].lower().split(" "): 
      my_counter += 1 
      print(my_counter) 
     if word in image["tags"]: 
      my_counter +=1 
      print(my_counter) 
    if my_counter > 0: 
     if not matches[search_term].values() or my_counter > matches[search_term].values()[0]: 
      matches[search_term][image["id"]] = my_counter 

     my_counter = 0 
+0

J'ai essayé d'exécuter le code que vous avez modifié et je reçois maintenant l'erreur: TypeError: ' L'objet dict_values ​​ne supporte pas l'indexation – Gray

+0

Python 3.4 renvoie dict_values ​​() au lieu de list lors de l'exécution de dict.values ​​(). il suffit de mettre list() autour des correspondances [search_term] .values ​​(). il devrait être comme list (correspond à [search_term] .values ​​()) [0] –

+0

Utilisez également la liste minuscule pour les étiquettes comme mis en évidence par un utilisateur ci-dessus. –