133 votes

Comment utiliser une fonction de comparaison personnalisée dans Python 3 ?

En Python 2.x Je pourrais passer une fonction personnalisée aux fonctions sorted et .sort.

>>> x=['kar','htar','har','ar']
>>>
>>> sorted(x)
['ar', 'har', 'htar', 'kar']
>>> 
>>> sorted(x,cmp=customsort)
['kar', 'htar', 'har', 'ar']

Car, en Mon La langue, les consonants viennent dans l'ordre suivant

"k","kh",....,"ht",..."h",...,"a"

Mais en Python 3.x Il semble que je ne puisse pas passer cmp mot-clé

>>> sorted(x,cmp=customsort)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'cmp' is an invalid keyword argument for this function

Existe-t-il d'autres solutions ou dois-je écrire ma propre fonction de tri ?

Note : J'ai simplifié en utilisant "k", "kh", etc. Les caractères réels sont des Unicodes et sont encore plus compliqués, parfois il y a des voyelles qui viennent avant et après les consonnes, j'ai fait une fonction de comparaison personnalisée, donc cette partie est ok. Le seul problème est que je ne peux pas passer ma fonction de comparaison personnalisée à sorted ou .sort.

77voto

aknuds1 Points 9918

Utiliser le key mot-clé et functools.cmp_to_key pour transformer votre fonction de comparaison :

sorted(x, key=functools.cmp_to_key(customsort))

64voto

Tim Pietzcker Points 146308

Utiliser le key (et suivre l'argument recette sur la façon de convertir votre ancienne cmp à une fonction key ).

functools a une fonction cmp_to_key mentionnée à l'adresse suivante docs.python.org/3.6/library/functools.html#functools.cmp_to_key

26voto

Charlie 木匠 Points 486

Un exemple complet de lambda cmp_to_key en python3 :

from functools import cmp_to_key

nums = [28, 50, 17, 12, 121]
nums.sort(key=cmp_to_key(lambda x, y: 1 if str(x)+str(y) < str(y)+str(x) else -1))

par rapport au tri d'objets courants :

class NumStr:
    def __init__(self, v):
        self.v = v
    def __lt__(self, other):
        return self.v + other.v < other.v + self.v

A = [NumStr("12"), NumStr("121")]
A.sort()
print(A[0].v, A[1].v)

A = [obj.v for obj in A]
print(A)

19voto

Daniel Stutzbach Points 20026

Au lieu d'un customsort(), vous avez besoin d'une fonction qui traduit chaque mot en quelque chose que Python sait déjà trier. Par exemple, vous pourriez traduire chaque mot en une liste de nombres où chaque nombre représente l'emplacement de chaque lettre dans votre alphabet. Quelque chose comme ceci :

my_alphabet = ['a', 'b', 'c']

def custom_key(word):
   numbers = []
   for letter in word:
      numbers.append(my_alphabet.index(letter))
   return numbers

x=['cbaba', 'ababa', 'bbaa']
x.sort(key=custom_key)

Comme votre langue comprend des lettres à plusieurs caractères, votre fonction custom_key devra évidemment être plus compliquée. Cela devrait cependant vous donner une idée générale.

4voto

Mark Tolonen Points 32702

Je ne sais pas si cela peut vous aider, mais vous pouvez consulter la page locale module. Il semble que vous puissiez régler la locale sur votre langue et utiliser locale.strcoll pour comparer des chaînes de caractères en utilisant les règles de tri de votre langue.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X