Tri liste de liste avec fonction de comparaison personnalisée en Python

je sais qu'il y a plusieurs questions nommées comme celle-ci, mais je n'arrive pas à obtenir leurs réponses pour travailler.

j'ai une liste de listes, 50 fois 5 éléments. Maintenant je veux trier cette liste en appliquant une fonction de comparaison personnalisée à chaque élément. Cette fonction calcule l'adéquation de la liste par laquelle les éléments doivent être triés. J'ai créé deux fonctions, de comparer et de remise en forme:

def compare(item1, item2):
    return (fitness(item1) < fitness(item2))

et

def fitness(item):
    return item[0]+item[1]+item[2]+item[3]+item[4]

Puis j'ai essayé de les appeler par:

sorted(mylist, cmp=compare)

ou

sorted(mylist, key=fitness)

ou

sorted(mylist, cmp=compare, key=fitness)

ou

sorted(mylist, cmp=lambda x,y: compare(x,y))

J'ai aussi essayé list.sort() avec les mêmes paramètres. Mais dans tous les cas les fonctions ne reçoivent pas une liste comme argument mais un None. Je n'ai aucune idée de la raison pour laquelle c'est, venant principalement de C++ cela contredit toute idée d'une fonction de rappel pour moi. Comment puis-je trier ces listes avec une fonction personnalisée?

Modifier J'ai trouvé mon erreur. Dans la chaîne qui crée le la première fonction list one ne retournait rien mais la valeur de retour était utilisée. Désolé pour la peine

41
demandé sur DaClown 2011-03-06 23:05:38

3 réponses

>>> l = [list(range(i, i+4)) for i in range(10,1,-1)]
>>> l
[[10, 11, 12, 13], [9, 10, 11, 12], [8, 9, 10, 11], [7, 8, 9, 10], [6, 7, 8, 9], [5, 6, 7, 8], [4, 5, 6, 7], [3, 4, 5, 6], [2, 3, 4, 5]]
>>> sorted(l, key=sum)
[[2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8], [6, 7, 8, 9], [7, 8, 9, 10], [8, 9, 10, 11], [9, 10, 11, 12], [10, 11, 12, 13]]

Les travaux ci-dessus. Faites-vous quelque chose de différent?

notez que votre fonction clé est juste sum; il n'est pas nécessaire de l'écrire explicitement.

24
répondu Katriel 2011-03-06 20:16:35

de plus, votre fonction de comparaison est incorrecte. Il doit retourner -1, 0, ou 1, pas une valeur booléenne que vous l'avez. La bonne comparaison serait:

def compare(item1, item2):
    if fitness(item1) < fitness(item2):
        return -1
    elif fitness(item1) > fitness(item2):
        return 1
    else:
        return 0
56
répondu Michael Mouse 2012-11-05 20:27:54

vous devez modifier légèrement votre compare fonction et utilisation functools.cmp_to_key pour passer à sorted. Exemple de code:

import functools

lst = [list(range(i, i+5)) for i in range(5, 1, -1)]

def fitness(item):
    return item[0]+item[1]+item[2]+item[3]+item[4]
def compare(item1, item2):
    return fitness(item1) - fitness(item2)

sorted(lst, key=functools.cmp_to_key(compare))

Sortie:

[[2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 8], [5, 6, 7, 8, 9]]

Fonctionne :)

8
répondu JustAC0der 2017-09-20 10:49:42