커스텀 Python 목록 정렬


96

나는 내 오래된 코드를 리팩토링하고 있었고 이것을 발견했습니다.

alist.sort(cmp_items)

def cmp_items(a, b):
    if a.foo > b.foo:
        return 1
    elif a.foo == b.foo:
        return 0
    else:
        return -1

코드는 작동하지만 (약 3 년 전에 작성했습니다!) Python 문서의 어느 곳에서도이 문서를 찾을 수 없으며 모두가 sorted()사용자 지정 정렬을 구현하는 데 사용 합니다. 누군가 이것이 왜 작동하는지 설명 할 수 있습니까?


sorted()와 sort()거의 같은 방법으로 정렬 제공 정의는, 호출 규칙의 차이를 모듈로.
— Russell Borogove 2012-08-07

2
실제로 일어나는 일은 key매개 변수 를 사용하는 것이 cmp함수 를 전달하는 것보다 선호 된다는 것입니다. (후자의 경우에도 3 파이썬에서 구현되지 않음)
— jsbueno

목록에있는 항목이 무엇인지에 따라 다소 모호합니다. 코드에 속성이 있어야 foo합니다. 그렇지 않으면 폭발합니다. 더 나은 사용자 정의 정의 __lt__()다음 수업을위한 방법 sorted()및 list.sort()아웃 - 오브 - 박스 작동합니다. (, BTW 정의 할 이상 필요 객체없는 __cmp__()단지를 __lt__(). 이 참조
— SMCI

답변:


60

여기에 문서화되어 있습니다 .

sort () 메서드는 비교를 제어하기위한 선택적 인수를 사용합니다.

cmp는 첫 번째 인수가 두 번째 인수보다 작은 지, 같은지 또는 큰지 여부에 따라 음수, 0 또는 양수를 반환해야하는 두 인수 (목록 항목)의 사용자 지정 비교 함수를 지정합니다. cmp = lambda x, y : cmp (x.lower (), y.lower ()). 기본값은 없음입니다.


덕분에 내가 여기에 확인하고 있었고, 메소드 서명에서 볼 수없는 miles82 docs.python.org/tutorial/datastructures.html
— 로렌조

링크 한 페이지에 동일한 텍스트가 표시되지 않습니다. 문서가 변경 되었습니까? 게다가을 사용하려고 cmp하면 TypeError: 'cmp' is an invalid keyword argument for this function. 여기서 무슨 일이 일어나고 있습니까?
— HelloGoodbye

1
@HelloGoodbye sort ()에는 Python 3에 cmp 인수가 없습니다. 이것은 문서 링크가 Python 2 용이었을 때의 오래된 답변 입니다. 여기 에서 이전 문서를 찾 거나 여기에서 자세한 내용을 읽을 수 있습니다 . Python 3을 사용하는 경우 대신 key 인수를 사용합니다.
— miles82

실제로 비교 기능을 제공하려면 어떻게해야합니까? 문자열의 숫자 (모든 길이, 탐욕스럽게 선택됨)를 개별 문자가 다르게 취급되는 방식과 동일하게 기호로 취급하고 싶습니다. 비교 기능을 제공 할 수 있다면 사소하게 달성하는 방법을 알고 있지만 핵심 기능을 제공해야하는 경우에는 그렇지 않습니다. 이것이 변경된 이유는 무엇입니까?
— HelloGoodbye

문자열에 포함 된 각 숫자가 Levenshtein coding 과 같이 사전 순으로 숫자를 정렬하는 인코딩을 사용하여 인코딩되면 여전히 달성 할 수 있다고 생각합니다 . 그러나 나는 사실을 해결 등이 더 생각 sort나는 것이 무엇인가 파이썬 3 인자로 비교 기능을, 그리고하지 않습니다 실제로 할 싶습니다.
— HelloGoodbye

108

참고로 다음은 동일한 정렬을 구현하는 더 나은 대안입니다.

alist.sort(key=lambda x: x.foo)

또는 :

import operator
alist.sort(key=operator.attrgetter('foo'))

Sorting How To를 확인하십시오 . 매우 유용합니다.


1
연산자에 대한 TIL, 매우 유용합니다.
— ffledgling

15

이 예처럼. 이 목록을 정렬하고 싶습니다.

[('c', 2), ('b', 2), ('a', 3)]

산출:

[('a', 3), ('b', 2), ('c', 2)]

두 번째 항목을 기준으로 튜플을 정렬 한 다음 첫 번째 항목을 정렬해야합니다.

def letter_cmp(a, b):
    if a[1] > b[1]:
        return -1
    elif a[1] == b[1]:
        if a[0] > b[0]:
            return 1
        else:
            return -1
    else:
        return 1

그런 다음 키 함수로 변환하십시오.

from functools import cmp_to_key
letter_cmp_key = cmp_to_key(letter_cmp))

이제 사용자 지정 정렬 순서를 사용할 수 있습니다.

[('c', 2), ('b', 2), ('a', 3)].sort(key=letter_cmp_key)

4
정렬 할 목록을 어떻게 알 수 있습니까?
— Cameron Monks 2019

2
@CameronMonks yourList.sort (letter_cmp)
— Minyc510

7

이것은 Python 3에서 작동하지 않습니다.

functools cmp_to_key를 사용하여 이전 스타일의 비교 함수가 작동하도록 할 수 있습니다.

from functools import cmp_to_key

def cmp_items(a, b):
    if a.foo > b.foo:
        return 1
    elif a.foo == b.foo:
        return 0
    else:
        return -1

cmp_items_py3 = cmp_to_key(cmp_items)

alist.sort(cmp_items_py3)

1

많은 사람들이 이미 좋은 답변을 올렸다는 것을 알고 있습니다. 그러나 라이브러리를 가져 오지 않고 멋지고 쉬운 방법을 제안하고 싶습니다.

l = [(2, 3), (3, 4), (2, 4)]
l.sort(key = lambda x: (-x[0], -x[1]) )
print(l)
l.sort(key = lambda x: (x[0], -x[1]) )
print(l)

출력은

[(3, 4), (2, 4), (2, 3)]
[(2, 4), (2, 3), (3, 4)]

출력은 튜플 형식으로 제공 한 매개 변수의 순서에 따라 정렬됩니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.