2010-09-08 4 views
4

J'ai un tuple de résultat de dictionnaires.Comment uniqufy l'élément tuple?

result = ({'name': 'xxx', 'score': 120L }, {'name': 'xxx', 'score': 100L}, {'name': 'yyy', 'score': 10L}) 

Je veux l'uniformiser. Après l'opération uniqify result = ({'name': 'xxx', 'score': 120L }, {'name': 'yyy', 'score': 10L})

Le result ne contiennent que one dictionary de chaque name et le dict devrait avoir maximum score. Le résultat final devrait être dans le même format, c'est-à-dire un tuple de dictionnaire.

Répondre

2
from operator import itemgetter 

names = set(d['name'] for d in result) 
uniq = [] 
for name in names: 
    scores = [res for res in result if res['name'] == name] 
    uniq.append(max(scores, key=itemgetter('score'))) 

Je suis sûr qu'il ya une solution plus courte, mais vous ne serez pas en mesure d'éviter le filtrage des scores par nom d'une certaine façon, puis trouver le maximum pour chaque nom.

Le stockage des scores dans un dictionnaire avec des noms comme clés serait certainement préférable ici.

+0

Je pense que vous trouvez le meilleur score, pas le meilleur score pour chaque nom unique. – Gabe

+0

@Gabe, Non Je trouve le meilleur score de chaque nom unique. Je modifie légèrement la question. Vérifiez-le. – user12345

+0

@Gabe: Vous avez raison ... J'ai été induit en erreur par l'existence d'un seul nom. –

2

Je voudrais créer un dictionnaire intermédiaire mappage de chaque nom à la note maximale pour ce nom, puis remettez-le à un tuple de dicts après:

>>> result = ({'name': 'xxx', 'score': 120L }, {'name': 'xxx', 'score': 100L}, {'name': 'xxx', 'score': 10L}, {'name':'yyy', 'score':20}) 
>>> from collections import defaultdict 
>>> max_scores = defaultdict(int) 
>>> for d in result: 
...  max_scores[d['name']] = max(d['score'], max_scores[d['name']]) 
... 
>>> max_scores 
defaultdict(<type 'int'>, {'xxx': 120L, 'yyy': 20}) 
>>> tuple({name: score} for (name, score) in max_scores.iteritems()) 
({'xxx': 120L}, {'yyy': 20}) 

Notes: J'ai ajouté 1) {'name': 'yyy', 'score': 20} à votre données d'exemple pour le montrer fonctionnant avec un tuple avec plus qu'un nom.

2) J'utilise un defaultdict qui suppose que la valeur minimale pour le score est zéro. Si le score peut être négatif, vous devrez changer le paramètre int de defaultdict (int) en une fonction qui renvoie un nombre inférieur au score possible minimum. Incidemment, je soupçonne que d'avoir un tuple de dictionnaires n'est pas la meilleure structure de données pour ce que vous voulez faire. Avez-vous envisagé des alternatives, comme avoir une seule dict, peut-être avec une liste de scores pour chaque nom?

+0

+1 pour la critique sur la structure des données –

1

Je revoir la structure de données pour répondre à vos besoins mieux (par exemple avec le nom dict haché avec la liste des scores que la valeur), mais je le ferais comme ceci:

import operator as op 
import itertools as it 

result = ({'name': 'xxx', 'score': 120L }, 
      {'name': 'xxx', 'score': 100L}, 
      {'name': 'xxx', 'score': 10L}, 
      {'name':'yyy', 'score':20}) 
# groupby 

highscores = tuple(max(namegroup, key=op.itemgetter('score')) 
        for name,namegroup in it.groupby(result, 
                key=op.itemgetter('name')) 
        ) 
print highscores 
0

Que diriez-vous ...

inp = ({'name': 'xxx', 'score': 120L }, {'name': 'xxx', 'score': 100L}, {'name': 'yyy', 'score': 10L}) 

temp = {} 
for dct in inp: 
    if dct['score'] > temp.get(dct['name']): temp[dct['name']] = dct['score'] 

result = tuple({'name': name, 'score': score} for name, score in temp.iteritems())