2010-11-28 5 views
3

J'ai un dictionnaire comme celui-ci. paires de valeurs clés ou nom d'utilisateur: nomPython triant plusieurs attributs

d = {"user2":"Tom Cruise", "user1": "Tom Cruise"} 

Mon problème est que je dois trier ces par le nom, mais si plusieurs utilisateurs contiennent le même nom comme au-dessus, je dois alors trier les par leur nom d'utilisateur. J'ai recherché la fonction triée mais je ne comprends pas vraiment le paramètre cmp et le lambda. Si quelqu'un pouvait expliquer ça et m'aider avec ça, ce serait génial! Merci :)

Répondre

6

cmp est obsolète. lambda fait juste une fonction.

sorted(d.iteritems(), key=operator.itemgetter(1, 0)) 
+0

la chose est que cela fait partie d'une mission pour ma classe et je ne suis pas autorisé à importer des bibliothèques comme opérateur. Ses seules fonctions intégrées. Je comprends ce que vous obtenez et j'ai essayé d'improviser. J'ai utilisé "trié (l, clé = lambda l: (l [0], l [1]))", pensez-vous que cela soit équivalent à ce que vous avez dit? – 1337holiday

+0

Pas tout à fait. 'lambda x: x ([1], x [0])' –

+0

cette fonction est donc trier les noms, mais si les noms sont les mêmes alors il trie le nom d'utilisateur, ou faut-il les garder la même position? Parce que j'en ai besoin de sorte que si les noms sont les mêmes, alors il trie par nom d'utilisateur. Merci beaucoup! – 1337holiday

5

Je vais juste développer la réponse d'Ignacio Vazquez-Abrams. cmp est obsolète. Ne l'utilisez pas. Utilisez plutôt l'attribut key.

lambda fait une fonction. C'est une expression et peut donc aller des endroits qu'une déclaration normale ne peut pas mais son corps est limité à une seule expression.

my_func = lambda x: x + 1 

Ceci définit une fonction qui prend un seul argument, et retourne xx + 1. lambda x, y=1: x + y définit une fonction qui prend un argument x, un argument optionnel y avec une valeur par défaut de 1 et renvoie x + y. Comme vous pouvez le voir, c'est vraiment comme une instruction def sauf que c'est une expression et limitée à une seule expression pour le corps.

Le but de l'attribut key est que sorted l'appellera pour chaque élément de la séquence à trier et utilisera la valeur qu'il renvoie pour comparaison.

list_ = ['a', 'b', 'c'] 
sorted(list_, key=lambda x: 1) 

Il suffit de lire le reste pour un exemple hypothétique. Je n'ai pas regardé le problème assez étroitement avant d'écrire ceci. Ce sera toujours éducatif, alors je vais laisser tomber. Nous ne pouvons pas vraiment dire beaucoup plus parce que

  1. Vous ne pouvez pas trier dict s. Avez-vous une liste de dicts s? Nous pourrions trier cela. Vous n'avez pas affiché de clé username.

Je suppose que c'est quelque chose comme

users = [{'name': 'Tom Cruise', 'username': user234234234, 'reputation': 1}, 
     {'name': 'Aaron Sterling', 'username': 'aaronasterling', 'reputation': 11725}] 

Si vous vouliez confirmer que je suis plus impressionnant que Tom Cruise, vous pouvez faire:

sorted(users, key=lambda x: x['reputation']) 

Cette passe juste une fonction qui renvoie la valeur 'reputation' pour chaque dictionnaire de la liste. Mais lambdas peut être plus lent. La plupart du temps operator.itemgetter est ce que vous voulez.

operator.itemgetter prend une série de clés et renvoie une fonction qui prend un objet et retourne un tuple de la valeur de son argument.

donc f = operator.itemgetter('name', 'username') renverra essentiellement la même fonction que lambda d: (d['name'], d['username']) La différence est qu'il devrait, en principe beaucoup plus vite et vous ne devez pas regarder lambda laid expressions.

Donc, pour trier une liste de dict s par nom et nom d'utilisateur, il suffit de faire

sorted(list_of_dicts, operator.itemgetter('name', 'username')) 

qui est exactement ce que suggère Ignacio Vazquez-Abrams.

+0

Il me semblait que la clé est le nom d'utilisateur, et la valeur est le nom réel. –

+0

@Ignacio - droit. J'ai quelque peu manqué les 'iteritems' dans votre solution. – aaronasterling

+0

OP spécifie le dict en tant que "paires de valeurs clés ou nom d'utilisateur: nom" bien que cela puisse avoir été modifié. J'ai manqué au début. –

0

Vous devez savoir que dict ne peut pas être triée. Mais python 2.7 & 3.1 ont cette classe collections.OrderedDict.

Ainsi,

>>> from collections import OrderedDict 
>>> d=OrderedDict({'D':'X','B':'Z','C':'X','A':'Y'}) 
>>> d 
OrderedDict([('A', 'Y'), ('C', 'X'), ('B', 'Z'), ('D', 'X')]) 
>>> OrderedDict(sorted((d.items()), key=lambda t:(t[1],t[0]))) 
OrderedDict([('C', 'X'), ('D', 'X'), ('A', 'Y'), ('B', 'Z')]) 
+0

oui en fait ce n'est pas grave si c'est un dict, tout ce que j'ai besoin est que si j'ai des noms et des noms d'utilisateurs, je dois trier les noms mais le problème se pose si deux personnes ou plus ont le même nom trier ces personnes par nom d'utilisateur (seulement ces personnes). – 1337holiday

Questions connexes