728x90
sort 기본
list
내장 타입에는 리스트이 원소를 여러 기준에 따라 정렬할 수 있는sort
메서드가 들어 있다.- 예를 들어 다음 코드는 정수 리스트를 작은 수부터 큰 수까지 순서대로 정렬한다.
numbers = [93, 86, 11, 68, 70]
numbers.sort()
print(numbers) # [11,68,70,86,93]
sort
메서드는 순서를 정할 수 있는 대부분의 내장타입(문자열, 부동소수점 등) 에 잘 작동한다.- 다음 예시는 건설 현장에서 사용하는 여러 도구를 표현하는 클래스의 인스턴스를 출력할 수 있는
__repr__
메서드와 함께 사용한다.
class Tool:
def __init__(self, name, weight):
self.name = name
self.weight = weight
def __repr__(self):
return f'Tool({self.name!r}, {self.weight})'
tools = [
Tool('수준계', 3.5),
Tool('해머', 1.25),
Tool('스크류드라이버', 0.5),
Tool('끌', 0.25),
]
sort
메서드가 호출하는 객체 비교 특별 메서드가 정의되있지 않으므로 아래 코드는 에러가 난다.
tools.sort()
기준 정보 기반 정렬
sort
는 원소 애트리뷰트나 인덱스 등으로 기준 정보를 정할 수 있다.lamda
를 통해 정렬 기준 정보로 정렬해보자- 아래는
name
이라는 필드 순으로 정리한 것이다.
print('미정렬:', repr(tools)) # 미정렬: [Tool('수준계', 3.5), Tool('해머', 1.25), Tool('스크류드라이버', 0.5), Tool('끌', 0.25)]
tools.sort(key=lambda x: x.name)
print('\n정렬: ', tools) # 정렬: [Tool('끌', 0.25), Tool('수준계', 3.5), Tool('스크류드라이버', 0.5), Tool('해머', 1.25)]
- 아래는
weight
를 기준으로 정렬하는 것이다.
tools.sort(key=lambda x: x.weight)
print('무게순 정렬:', tools) # 무게순 정렬: [Tool('끌', 0.25), Tool('스크류드라이버', 0.5), Tool('해머', 1.25), Tool('수준계', 3.5)]
- 대소문자를 무시하고도 정렬이 가능하다.
places = ['home', 'work', 'New York', 'Paris']
places.sort()
print('대소문자 구분:', places) # 대소문자 구분: ['New York', 'Paris', 'home', 'work']
places.sort(key=lambda x: x.lower())
print('대소문자 무시:', places) # 대소문자 무시: ['home', 'New York', 'Paris', 'work']
- 때로는 여러 기준을 바탕으로 정렬할 수도 있다.
power_tools = [
Tool('드릴', 4),
Tool('원형 톱', 5),
Tool('착암기', 40),
Tool('연마기', 4),
]
- 파이썬은 불변 자료형인 튜플이 있는데, 기본적으로 튜플은 대소를 비교할 때 사전식(lexicographical) 비교를 하는데, 첫 번째 요소가 같다면 다음 요소를 넘어가 비교하는 식으로 동작한다.
saw = (5, '원형 톱')
jackhammer = (40, '착암기')
assert (jackhammer < saw) # False
drill = (4, '드릴')
sander = (4, '연마기')
assert drill[0] == sander[0] # # True
assert drill[1] < sander[1] # True
assert drill < sander # True
- 이러한 논리로 위해서 정한
power_tools
를 정렬해보자 sort
메서드는 튜플로 여러 기준을 나열하여 정렬할 수 있다.
power_tools.sort(key=lambda x: (x.weight, x.name))
print(power_tools) # [Tool('드릴', 4), Tool('연마기', 4), Tool('원형 톱', 5), Tool('착암기', 40)]
reverse=True
를 활용해 내림차순 정렬도 가능하다.
power_tools.sort(key=lambda x: (x.weight, x.name), reverse=True) # 모든 비교 기준을 내림차순으로 만든다
print(power_tools) # [Tool('착암기', 40), Tool('원형 톱', 5), Tool('연마기', 4), Tool('드릴', 4)]
sort와 sorted의 차이
sorted
라는 함수가 있는 데, 이는 새로 리스트를 반환하는 함수이다.
sorted_list = sorted(tools, key=lambda x: x.name) # 새로운 리스트 반환
tools.sort(key=lambda x: x.name) # 리스트 자체를 정렬
lambda 대신 operator.attrgetter의 정렬
operator.attrgetter
를 사용하여 여러 기준으로 정렬할 때, 하나의 필드가 아닌 여러 필드를 지정할 수 있다. 이는 람다 함수 대신 더 간결하고 읽기 쉽게 코드를 작성하는 방법이다.
from operator import attrgetter
class Tool:
def __init__(self, name, weight):
self.name = name
self.weight = weight
def __repr__(self):
return f'Tool({self.name!r}, {self.weight})'
tools = [
Tool('수준계', 3.5),
Tool('해머', 1.25),
Tool('스크류드라이버', 0.5),
Tool('끌', 0.25),
]
# 여러 기준으로 정렬: weight 먼저, 그 다음 name으로 정렬
tools.sort(key=attrgetter('weight', 'name'))
print(tools) # [Tool('끌', 0.25), Tool('스크류드라이버', 0.5), Tool('해머', 1.25), Tool('수준계', 3.5)]
728x90
'Programming Language > Python' 카테고리의 다른 글
BETTER WAY 21 - 변수 영역과 클로저의 상호작용 방식을 이해하라 (0) | 2024.11.25 |
---|---|
BETTER WAY 15 - 딕셔너리 삽입 순서에 의존할 떄는 조심하라 (2) | 2024.11.11 |
BETTER WAY 13 - 슬라이싱보다는 나머지를 모두 잡아내는 언패킹을 사용하라 (1) | 2024.10.10 |
BETTER WAY 12 - 스트라이드와 슬라이스를 한 식에 함께 사용하지 말라 (0) | 2024.09.20 |
BETTER WAY 10 - 대입식을 사용해 반복을 피하라 (1) | 2024.09.12 |