Python 3에서 사용자 지정 비교 함수를 사용하는 방법은 무엇입니까?


98

Python 2.x 에서는 사용자 지정 함수를 sorted 및 .sort 함수에 전달할 수 있습니다.

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

에 있기 때문에 언어, consonents은이 순서와 함께 제공

"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"등을 사용하여 단순화했습니다. 실제 문자는 유니 코드이고 훨씬 더 복잡합니다. 때로는 자음 전후에 모음이 나오는 경우가 있습니다. 사용자 지정 비교 기능을 수행 했으므로 해당 부분은 괜찮습니다. 문제는 사용자 지정 비교 함수를 sorted 또는 .sort에 전달할 수 없다는 것입니다.


방금 시도해 보셨습니까 sorted(x)?
SilentGhost

때문에 @SilentGhost는 만들 수 있는지, 난 그냥, 물론 작동하지 않는 가운데, 다시 시도 원래 언어 정렬 할 수있는 운영 시스템에 의해 로케일 목록을 지원하지 않습니다.
YOU

1
cmp를 핵심 기능으로 감쌀 수 있습니다. HowToSorting 사이트에서 cmp_to_key를 검색하십시오.
Frank

답변:


50

key인수를 사용하고 이전 함수를 함수 로 변환하는 방법에 대한 레시피 를 따르십시오 .cmpkey

functoolsdocs.python.org/3.6/library/functools.html#functools.cmp_to_key에cmp_to_key 언급 된 함수가 있습니다.


+1, 레시피가 해결 방법을 제공하는 것처럼 보이지만 모든 비교 연산자 < > = 를 중개자에게 전달하여 성능을 잃을 것 같습니다. 원래 사용자 정의 정렬이 C로 작성 되었기 때문에 약 1/2 배 속도를 가졌습니다. 기본 정렬.
YOU

2
(귀하의 프로필 만 보았습니다) 귀사가 Google 및 StackOverflow에 대한 액세스를 차단하고 있습니까? 그들은 얼마나 어리 석을 수 있습니까? 그러나 귀하의 응답에 대해 : 실제 성능 저하에 관심이 있습니다. 할 수 있습니까 timeit?
Tim Pietzcker

4
몇 가지 벤치 마크를 수행했는데 사용자 지정 C 비교 함수를 직접 전달하는 것보다 약 4 배 느립니다.
YOU

2
키 기능과 cmp 기능이 모두 필요한 경우 어떻게합니까? 각 사전의 사용자 정의 키로 사전 목록을 정렬하고 싶습니다. sorted_rows = sorted(rows, key=itemgetter('name'), cmp=locale.strxfrm)TypeError 제공 : 'cmp'는 Python 3.2에서이 함수에 대한 잘못된 키워드 인수입니다. :(
bitek

4
functools에는 표준 라이브러리에 cmp_to_key 함수가 있습니다. docs.python.org/3.6/library/functools.html
Martín Fixman


17

customsort () 대신 각 단어를 파이썬이 이미 정렬하는 방법을 알고있는 것으로 번역하는 함수가 필요합니다. 예를 들어 각 단어를 숫자 목록으로 번역 할 수 있습니다. 여기서 각 숫자는 알파벳에서 각 문자가 나오는 위치를 나타냅니다. 이 같은:

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 함수는 분명히 더 복잡해야합니다. 그래도 일반적인 아이디어를 얻을 수 있습니다.


감사합니다 +1, ICU 방식입니다. 하지만 언어에는 단어 구분자가없고 표준 로마자 표기 규칙이 없기 때문에 조사하는 데 시간이 걸릴 것 같습니다.
YOU

9

완전한 python3 cmp_to_key 람다 예제 :

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)

4

이것이 도움이 될지 모르겠지만 locale모듈을 확인해보십시오 . 로케일을 귀하의 언어로 설정하고 locale.strcoll언어의 정렬 규칙을 사용하여 문자열을 비교 하는 데 사용할 수있는 것 같습니다 .


그것은 인기있는 언어의 경우 사실이지만 언어는 운영 체제, ICU 및 unicode.org에서 완전히 지원되지 않으므로 의문의 여지가 없지만 좋은 제안에는 +1입니다.
YOU

-2

key대신 인수를 사용하십시오 . 처리중인 값을 가져와 정렬 기준으로 사용할 키를 제공하는 단일 값을 반환하는 함수를 사용합니다.

sorted(x, key=somekeyfunc)

3
키는 하나의 매개 변수 기능 만 허용하고 cmp에는 2 개의 매개 변수가 있으며 서로 다른 동작입니다. 키 키워드가 하나의 매개 변수 만 전달하기 때문에 방금 테스트했는데 오류가 발생했습니다.TypeError: customsort() takes exactly 2 positional arguments (1 given)
YOU
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.