IT박스

두 개의 필드로 파이썬리스트 정렬

itboxs 2020. 6. 9. 22:16
반응형

두 개의 필드로 파이썬리스트 정렬


정렬 된 CSV로 만든 다음 목록이 있습니다.

list1 = sorted(csv1, key=operator.itemgetter(1))

실제로 목록을 두 가지 기준으로 정렬하고 싶습니다. 먼저 필드 1의 값을 기준으로 한 다음 필드 2의 값을 기준으로 정렬합니다. 어떻게해야합니까?


이처럼 :

import operator
list1 = sorted(csv1, key=operator.itemgetter(1, 2))

아카이브를 위해이 스레드에 응답합니다.

람다 함수를 사용할 때 아무 것도 가져올 필요가 없습니다.
다음 list은 첫 번째 요소를 기준으로 정렬 다음 두 번째 요소를 기준으로 정렬 합니다.

sorted(list, key=lambda x: (x[0], -x[1]))

파이썬은 안정적인 정렬을 가지고 있으므로 성능이 문제가되지 않는 가장 간단한 방법은 필드 2로 정렬 한 다음 필드 1로 다시 정렬하는 것입니다.

그것은 당신에게 당신이 원하는 결과를 줄 것입니다, 유일한 캐치는 그것이 큰 목록이라면 (또는 당신이 그것을 자주 정렬하고 싶다면) sort를 두 번 호출하는 것은 용납 할 수없는 오버 헤드 일 수 있다는 것입니다.

list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))

이 방법을 사용하면 일부 열의 역 정렬을 원하는 상황을 쉽게 처리 할 수 ​​있습니다. 필요한 경우 'reverse = True'매개 변수 만 포함하면됩니다.

그렇지 않으면 여러 매개 변수를 itemgetter에 전달하거나 수동으로 튜플을 빌드 할 수 있습니다. 아마 더 빠를 지 모르지만 일부 열이 역 정렬되기를 원한다면 잘 일반화되지 않는다는 문제가 있습니다 (숫자 열은 무시하여 정렬 할 수는 있지만 정렬이 안정적이지 않습니다).

따라서 역 정렬 된 열이 필요하지 않으면 여러 인수를 itemgetter로 이동하십시오. 가능한 경우 열이 숫자가 아니거나 여러 연속 정렬을 위해 정렬을 안정적으로 유지하려고합니다.

편집 : 이것이 원래의 질문에 어떻게 대답하는지 이해하는 데 어려움을 겪는 주석가의 경우, 정렬의 안정적인 특성으로 각 키에 대해 개별 정렬을 수행하고 여러 기준으로 정렬 된 데이터로 끝내는 방법을 정확하게 보여주는 예가 있습니다.

DATA = [
    ('Jones', 'Jane', 58),
    ('Smith', 'Anne', 30),
    ('Jones', 'Fred', 30),
    ('Smith', 'John', 60),
    ('Smith', 'Fred', 30),
    ('Jones', 'Anne', 30),
    ('Smith', 'Jane', 58),
    ('Smith', 'Twin2', 3),
    ('Jones', 'John', 60),
    ('Smith', 'Twin1', 3),
    ('Jones', 'Twin1', 3),
    ('Jones', 'Twin2', 3)
]

# Sort by Surname, Age DESCENDING, Firstname
print("Initial data in random order")
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred''')
DATA.sort(key=lambda row: row[1])

for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.''')
DATA.sort(key=lambda row: row[2], reverse=True)
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
''')
DATA.sort(key=lambda row: row[0])
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

이것은 실행 가능한 예제이지만 실행하는 사람들을 저장하기 위해 출력은 다음과 같습니다.

Initial data in random order
Jones      Jane       58
Smith      Anne       30
Jones      Fred       30
Smith      John       60
Smith      Fred       30
Jones      Anne       30
Smith      Jane       58
Smith      Twin2      3
Jones      John       60
Smith      Twin1      3
Jones      Twin1      3
Jones      Twin2      3

First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred
Smith      Anne       30
Jones      Anne       30
Jones      Fred       30
Smith      Fred       30
Jones      Jane       58
Smith      Jane       58
Smith      John       60
Jones      John       60
Smith      Twin1      3
Jones      Twin1      3
Smith      Twin2      3
Jones      Twin2      3

Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.
Smith      John       60
Jones      John       60
Jones      Jane       58
Smith      Jane       58
Smith      Anne       30
Jones      Anne       30
Jones      Fred       30
Smith      Fred       30
Smith      Twin1      3
Jones      Twin1      3
Smith      Twin2      3
Jones      Twin2      3

Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.

Jones      John       60
Jones      Jane       58
Jones      Anne       30
Jones      Fred       30
Jones      Twin1      3
Jones      Twin2      3
Smith      John       60
Smith      Jane       58
Smith      Anne       30
Smith      Fred       30
Smith      Twin1      3
Smith      Twin2      3

특히 두 번째 단계에서 reverse=True매개 변수가 어떻게 이름을 순서대로 유지 하는가에 따라 목록을 단순히 정렬 한 후 뒤집 으면 세 번째 정렬 키에 대해 원하는 순서를 잃게됩니다.


def keyfunc(x):
    return tuple(x[1],x[2])

list1 = sorted(csv1, key=keyfunc)

employees.sort(key = lambda x:x[1])
employees.sort(key = lambda x:x[0])

파이썬 정렬이 제자리에 있고 안정적이기 때문에 .sort를 lambda와 함께 2 번 사용할 수도 있습니다. 먼저 두 번째 요소 x [1]에 따라 목록을 정렬합니다. 그런 다음 첫 번째 요소 x [0] (가장 높은 우선 순위)을 정렬합니다.

직원 [0] = 직원 이름 직원 [1] = 직원 급여

This is equivalent to doing the following: employees.sort(key = lambda x:(x[0], x[1]))


In ascending order you can use:

sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]))

or in descending order you can use:

sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]),reverse=True)

Sorting list of dicts using below will sort list in descending order on first column as salary and second column as age

d=[{'salary':123,'age':23},{'salary':123,'age':25}]
d=sorted(d, key=lambda i: (i['salary'], i['age']),reverse=True)

Output: [{'salary': 123, 'age': 25}, {'salary': 123, 'age': 23}]

참고URL : https://stackoverflow.com/questions/5212870/sorting-a-python-list-by-two-fields

반응형