2016-11-30 4 views
2

J'ai un dictionnaire que j'ai créé en lisant dans un tas de fichiers image. Il ressemble à ceci:Le moyen le plus efficace de comparer toutes les valeurs dans un dictionnaire?

files = { 'file1.png': [data...], 'file2.png': [data...], ... 'file1000': [data...]} 

Je suis en train de traiter ces images pour voir comment similaires chacun d'entre eux sont les uns aux autres. La chose est, avec des milliers de fichiers de valeur de données, cela prend une éternité. Je suis sûr que j'ai 20 endroits différents que je pourrais optimiser, mais j'essaie de travailler à travers un morceau à la fois pour voir comment je peux mieux l'optimiser.

Ma méthode originale a testé file1 pour tous les autres fichiers. Ensuite, j'ai testé fichier2 contre tous les fichiers. Mais je l'ai encore testé contre file1. Donc, au moment où j'arrive à file1000 dans l'exemple ci-dessus, je n'aurais même pas besoin de tester quoi que ce soit à ce stade, car il a déjà été testé 999 fois.

C'est ce que j'ai essayé:

answers = {} 
for x in files: 
    for y in files: 
     if y not in answers or x not in answers[y]: 
      if(compare(files[x],files[y]) < 0.01): 
       answers.setdefault(x, []).append(y) 

Cela ne fonctionne pas, comme je reçois la mauvaise sortie maintenant. La fonction de comparaison est juste ceci:

rms = math.sqrt(functools.reduce(operator.add,map(lambda a,b: (a-b)**2, h1[0], h2[0]))/len(h1[0])) 
return rms 

Je ne voulais simplement pas mettre cette énorme équation dans l'instruction if.

Est-ce que quelqu'un a une bonne méthode pour comparer chacun des segments de données du dictionnaire de fichiers sans chevaucher les comparaisons?

Edit:

Après avoir essayé la réponse de ShadowRanger je me suis rendu compte que je ne peux pas avoir compris ce que je avais besoin. Mes réponses d'origine dictionnaire ressemblait à ceci:

{ 'file1.png': ['file1.png', 'file23.png', 'file333.png'], 
    'file2.png': ['file2.png'], 
    'file3.png': ['file3.png', 'file4.png', 'file5.png'], 
    'file4.png': ['file3.png', 'file4.png', 'file5.png'], 
    ...} 

Et pour l'instant je stocke mes résultats dans un fichier comme celui-ci:

file1.png file23.png file33.png 
file2.png 
file3.png file4.png file5.png 
file6.png 
... 

Je pensais qu'en utilisant des combinaisons et seulement tester des fichiers individuels une fois que je serais économiser beaucoup de temps retesting des fichiers et ne pas perdre de temps à se débarrasser des réponses en double. Mais pour autant que je sache, les combinaisons ont réduit ma capacité à trouver des allumettes et je ne sais pas pourquoi.

+0

opérations d'utilisation définies sur les vues dict, à savoir dict.keys() ou (dict.items). – pylang

+0

@pylang Il n'y a pas de fichiers en double, c'est-à-dire de clés, et je ne veux pas me débarrasser d'un ensemble de données car je veux voir quels fichiers sont similaires les uns aux autres. Edit: Si vous vous référez à la réponse, c'est ce que j'ai commencé avec. Mais quand j'ai augmenté mon jeu de données à 1000 fichiers, j'ai fini par quitter le programme après 5 minutes d'exécution. – user1362058

+1

Si vous avez affaire à des images, est-il vraiment sûr de charger tous les fichiers en mémoire? Vous dites que vous pourriez avoir des milliers de fichiers, mais avez-vous réellement mis les données brutes de mille images dans un dictionnaire? Si elles sont censées être des icônes ou des images aussi petites, alors ça va ... mais avec des photos, votre ordinateur devrait exploser (à moins que Python ne fasse de la magie, je ne sais pas là-bas). –

Répondre

2

Vous pouvez éviter les comparaisons redondantes with itertools.combinations to get order-insensitive unique pairs. Juste import itertools et remplacer votre boucle double imbriquée:

for x in files: 
    for y in files: 

avec une seule boucle qui obtient les combinaisons:

for x, y in itertools.combinations(files, 2): 
+0

Ouais cela devrait fonctionner puisque l'itérateur de 'combinations' ne devrait pas prendre de mémoire et que vous ne comparez que deux fichiers à la fois. Agréable. – pylang

+0

J'ai imprimé les combinaisons et il semble que cela fonctionne, sauf que je ne reçois pas la bonne sortie. Je pense que j'ai fait une grave erreur ... – user1362058

+0

@ShadowRanger Je pense que j'ai peut-être trouvé le/un problème. J'en ai besoin pour correspondre avec lui-même aussi. Au moins, comme j'ai mis en place le dictionnaire de réponses, j'ai besoin que chaque fichier ait une correspondance positive, même si cela signifie que c'est seulement avec lui-même. – user1362058