如何在Python 3中使用自定义比较功能?

问题:如何在Python 3中使用自定义比较功能?

Python 2.x中,我可以将自定义函数传递给sort和.sort函数

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

因为用我的语言,辅音是伴随着这个顺序

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

但是在Python 3.x中,看起来我无法传递cmp关键字

>>> 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

有其他选择吗?或者我也应该编写自己的排序函数吗?

注意:我通过使用“ k”,“ kh”等进行了简化。实际字符是Unicode,甚至更复杂,有时在辅音前后都有元音,所以我完成了自定义比较功能,因此这一部分还可以。唯一的问题是我无法将自定义比较功能传递给sort或.sort

In Python 2.x, I could pass custom function to sorted and .sort functions

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

Because, in My language, consonents are comes with this order

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

But In Python 3.x, looks like I could not pass cmp keyword

>>> 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

Is there any alternatives or should I write my own sorted function too?

Note: I simplified by using “k”, “kh”, etc. Actual characters are Unicodes and even more complicated, sometimes there is vowels comes before and after consonents, I’ve done custom comparison function, So that part is ok. Only the problem is I could not pass my custom comparison function to sorted or .sort


回答 0

使用key参数(并按照配方上如何将旧的转换cmp功能的key功能)。

functoolscmp_to_keydocs.python.org/3.6/library/functools.html#functools.cmp_to_key中提到了一个功能

Use the key argument (and follow the recipe on how to convert your old cmp function to a key function).

functools has a function cmp_to_key mentioned at docs.python.org/3.6/library/functools.html#functools.cmp_to_key


回答 1

使用key关键字和functools.cmp_to_key转换比较功能:

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

Use the key keyword and functools.cmp_to_key to transform your comparison function:

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

回答 2

而不是customsort(),您需要一个函数来将每个单词转换为Python已经知道如何排序的东西。例如,您可以将每个单词转换为数字列表,其中每个数字代表每个字母在字母表中的位置。像这样:

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)

由于您的语言包括多字符字母,因此您的custom_key函数显然需要更加复杂。那应该给您大致的想法。

Instead of a customsort(), you need a function that translates each word into something that Python already knows how to sort. For example, you could translate each word into a list of numbers where each number represents where each letter occurs in your alphabet. Something like this:

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)

Since your language includes multi-character letters, your custom_key function will obviously need to be more complicated. That should give you the general idea though.


回答 3

完整的python3 cmp_to_key lambda示例:

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))

与普通对象排序相比:

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)

A complete python3 cmp_to_key lambda example:

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))

compare to common object sorting:

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)

回答 4

我不知道这是否有帮助,但是您可以签出该locale模块。看起来您可以将语言环境设置为您的语言,并使用locale.strcoll您的语言的排序规则来比较字符串。

I don’t know if this will help, but you may check out the locale module. It looks like you can set the locale to your language and use locale.strcoll to compare strings using your language’s sorting rules.


回答 5

请改用key参数。它采用一个函数,该函数接受要处理的值,并返回单个值,该值给出了用于排序的键。

sorted(x, key=somekeyfunc)

Use the key argument instead. It takes a function that takes the value being processed and returns a single value giving the key to use to sort by.

sorted(x, key=somekeyfunc)