[Python] sort()와 sorted() — 원본 변경과 정렬 기준 구분하기

차곡코딩·5일 전

Python · 기초 문법

목록 보기
4/7

정렬 결과뿐 아니라 원본도 확인하기

정렬 코드를 읽을 때는 결과의 순서와 원본 변경 여부를 따로 확인해야 한다. list.sort()는 원본 리스트를 정렬하고 None을 반환한다. sorted()는 정렬된 새 리스트를 반환한다.

numbers = [4, 1, 3]
ordered = sorted(numbers)
print(numbers)
print(ordered)

result = numbers.sort()
print(numbers)
print(result)
[4, 1, 3]
[1, 3, 4]
[1, 3, 4]
None

numbers = numbers.sort()로 작성하면 정렬된 리스트가 아니라 None이 변수에 저장된다. 원본을 유지해야 하는 경우에는 sorted(numbers)가 의도를 명확하게 드러낸다.

key는 비교할 기준을 만든다

다음 데이터는 (이름, 점수) 형식이다. 점수 내림차순으로 정렬하고, 점수가 같으면 이름 오름차순으로 정렬한다.

students = [("Min", 90), ("Ara", 90), ("Jun", 80)]
ranked = sorted(students, key=lambda row: (-row[1], row[0]))
print(ranked)
print(students)
[('Ara', 90), ('Min', 90), ('Jun', 80)]
[('Min', 90), ('Ara', 90), ('Jun', 80)]

비교 키는 차례로 (-90, 'Min'), (-90, 'Ara'), (-80, 'Jun')이다. 튜플의 첫 항목을 먼저 비교하고 같으면 다음 항목을 비교한다. 점수에 음수를 붙여 점수만 내림차순으로 만들었다. 이 방법은 여기처럼 수치형 점수에 적용한다.

전체 키에 reverse=True를 적용하면 이름까지 내림차순이 된다. 여러 기준의 방향이 다를 때는 각 기준을 분리해서 생각해야 한다.

안정 정렬은 동점자의 원래 순서를 보존한다

students = [("Min", 90), ("Ara", 90), ("Jun", 80)]
print(sorted(students, key=lambda row: row[1], reverse=True))
[('Min', 90), ('Ara', 90), ('Jun', 80)]

점수만 비교했으므로 같은 90점인 Min과 Ara는 입력 순서를 유지한다. 이것이 안정 정렬이다. 다만 안정 정렬이 이름순까지 보장하는 것은 아니다. 이름순이 요구사항이라면 앞의 예제처럼 두 번째 비교 기준을 명시해야 한다.

새 리스트와 깊은 복사는 다르다

sorted()가 새 리스트를 만든다고 해서 내부의 가변 객체까지 모두 복제하는 것은 아니다. 이번 예제의 원소는 튜플이지만, 원소가 딕셔너리나 리스트라면 정렬 전후의 리스트가 같은 내부 객체를 참조할 수 있다. 원본의 순서 보존과 내부 데이터의 독립성은 별개의 조건이다.

정리

정렬 전에 원본 변경 허용 여부, 첫 번째 기준, 동률일 때의 기준을 정한다. sort()와 sorted()의 선택은 첫 번째 조건에, key의 구성은 나머지 두 조건에 대응한다.

참고

profile
비전공자의 개발 성장 기록. 바이브코딩 프리랜서 경험부터 Python·SQL·AI 서비스 개발까지

0개의 댓글