2010-11-06 21 views
2

Pendant que je débogage une behavour illogique que je suis venu à la bizarrerie suivante dans Python 2.5 trié() appels de fonction:Python triée() fonction clé bizarreries

>>> aa = [10, 5, 20] 
>>> sorted(range(len(aa))) 
[0, 1, 2] 
sorted(range(len(aa)), key=lambda a: aa[a]) 
[1, 0, 2] 
sorted(range(len(aa)), key=lambda a: -aa[a]) 
[2, 0, 1] 

deux premiers appels fonctionnent comme prévu, mais le le dernier est imho simplement mauvais! Ce devrait être: [1, 2, 0].

Après d'autres expériences pour essayer de venir à la racine du problème que je suis venu à cette (ne pas utiliser lambda ou opération de négation, mais il est par ailleurs le même problème):

>>> bb = [-10, -5, -20] 
>>> sorted([0, 1, 2], key=bb.__getitem__) 
[2, 0, 1] 

Même les choses comme suit ne fonctionne pas et montre que la double négation fonctionne à nouveau:

>>> bb = [-10, -5, -20] 
>>> def fun(i): 
... return bb[i] 
>>> sorted([0, 1, 2], key=fun) 
[2, 0, 1] 
>>> def fun2(i): 
...  return -bb[i] 
>>> sorted([0, 1, 2], key=fun2) 
[1, 0, 2] 

Est-ce que je perds la tête ou quel est le problème? Ou pourquoi Python 3.x n'a-t-il pas l'argument cmp qui fonctionnait bien (la compatibilité est la raison pour laquelle je ne l'utilise pas)?

+2

Pourquoi le troisième résultat est-il faux? Les valeurs que vous triez sont '[0, 1, 2]', et les touches '[-10, -5, -20]'. Sorted qui se traduirait par '[-20, -10, -5]', ce qui donne '[2, 0, 1]' pour les valeurs ... – adw

+0

Oups, tout va bien! Je ne sais pas pourquoi je pensais que cela devrait retourner quelque chose comme: >>> bb = [-1, -1, -1] >>> j = 0 >>> pour moi en trié (gamme (len (aa)), clé = lambda a: -aa [a]): ... bb [i] = j ... j + = 1 >>> bb [1, 2, 0] – gw0

Répondre

8

La valeur renvoyée par la fonction de clé sert de proxy pour les valeurs triées. Alors, quand vous dites

sorted(range(len(aa)), key=lambda a: -aa[a]) 

vous triez range(len(aa)), qui est [0, 1, 2], mais en utilisant les valeurs -aa[0], -aa[1], -aa[2] que les valeurs de proxy.

range(len(aa)) 0 1 2 <-- values 
aa[a]   10 5 20 
-aa[a]   -10 -5 -20 <-- proxy values 

Depuis -20, ou -aa[2], est la plus petite valeur de proxy, la valeur 2 associé devient le premier élément dans le résultat trié.Comme -10 ou -aa[0] est le plus petit suivant, sa valeur associée 0 devient le deuxième élément du résultat trié.

Enfin -5, ou -aa[1] est la dernière valeur, donc 1 est le dernier chiffre du résultat trié. Par conséquent, sorted(range(len(aa)), key=lambda a: -aa[a]) est égal à [2, 0, 1].

La réponse de Python est correcte.

0

Cela me paraît logique

>>> bb = [-10, -5, -20] 
>>> sorted([0, 1, 2], key=bb.__getitem__) 
[2, 0, 1] ==> corresponds to bb.__getitem__ of [-20, -10, -5] 
+1

Je n'ai jamais vu d'empreinte python '==> correspond à bb .__ getitem__ de [-20, -10, -5]' –

+0

Je n'ai pas non plus vu de personnes qui semblent parler deux langues :) (Toutes mes excuses pour m'amuser sur SO! Reprise du visage grincheux!) –

1

le dernier est tout simplement IMHO mal! Il doit être: [1, 2, 0]

Dans votre deuxième exemple, la clé est lambda a: aa[a] qui vous donne les indices des éléments dans l'ordre de taille croissant.

Dans le dernier exemple, la clé est lambda a: -aa[a]. En raison de la négation, cela vous donne les indices des éléments dans décroissant ordre de taille. Le dernier résultat devrait être [2, 0, 1] - c'est l'inverse de [1, 0, 2].

Dans cet exemple

>>> bb = [-10, -5, -20] 
>>> sorted([0, 1, 2], key=bb.__getitem__) 
[2, 0, 1] 

vous obtenez les indices des éléments en ordre croissant de taille - [2, 0, 1] correspond à [-20, -10, -5]. Dans vos deux derniers exemples, vous obtenez à nouveau les indices pour les éléments en ordre croissant de taille ([2, 0, 1]) ou en ordre de taille décroissant ([1, 0, 2]).