sort 메서드 & key parameter 을 쓰자.
- sort 메서드는 자연스럽게 순서를 정할 수 있는 거의 대부분의 내장타입(str, float, list 등)에 잘 작동한다.
- 하지만 아래와 같은 경우는 동작하지 않는다.
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),
]
tools.sort() >>> Tracback...
- 위의 경우 sort를 위한 magic method (
__lt__
) 가 정의되지 않아서 생긴 에러인데, 여기서 magic method를 추가하기 보다는 sort의 key 파라미터 를 쓰는 것이 낫다.
- 왜냐하면, 만든 객체가 여러 가지 순서를 지원해야하는 경우가 더 많기 때문이다.
- key 파라미터에는 함수가 들어가야 하고, 함수의 argument에는 "정렬 중인 리스트의 원소"가 전달된다.
tools.sort(key=lambda x: x.name)
>>>
[Tool('끝', 0.25), Tool('수준계', 3.5), Tool('스크류드라이버', 0.5), Tool('해머', 1.25)]
- 심지어 문자열 같은 기본 타입의 경우에는, 정렬하기 전에 key 함수를 이용해 원소 값을 변경한 채로 sort 할 수도 있다.
places = ['home', 'work', 'New York', 'Paris']
places.sort(key=lambda x: x.lower())
- sort에 reverse parameter 도 쓸 수 있다. (내림차순 하고 싶으면 쓰자)
tools.sort(key=lambda x: x.name, reverse=True)
여러 기준으로 sort 하기
- 여러 기준으로 sort하고 싶을 때? : tuple 로 비교하자!
- 튜플은 튜플의 각 위치를 iteration 하면서, 각 index에 해당하는 원소를 한번에 하나씩 비교한다.
- 즉, 튜플은 첫 번째 위치에 있는 값이 서로 같으면, 두 번째 위치에 있는 값을 비교한다.
drill = (4, '드릴')
sander = (4, '연마기')
power_tools.sort(key=lambda x: (x.weight, x.name)
assert drill[0] == sander[0]
assert drill[1] < sander[1]
assert drill < sander
- 단점
- 튜플에 sort(key= ~~)를 쓰는 것의 단점은, 모든 비교 기준의 정렬 순서가 같아야 한다는 점(모두 오름차순이거나 모두 내림차순)
power_tools.sort(key=lambda x: (x.weight, x.name),
reverse=True)
- 어떤 기준은 오름차순, 어떤 기준은 내림차순으로 하고 싶으면??
- 방법 1
- minus 를 붙여라.
- (방법 1로 해결되면 방법2 말고 1을 쓰는 것을 권장한다.)
- 코드가 더 적고 읽기도 쉽기 때문이다.
power_tools.sort(key=lambda x: (-x.weight, x.name))
print(power_tools)
- 방법 2
- 위 예시에서, x.name 같은 경우는 minus 등을 붙일 수 없다.
- 아래 예제는, weight 순서로 먼저 정렬한 후, 그 다음 동점자에 대해 name으로 정렬 하고 싶은 경우이다. (코드의 순서는 반대로 된다.)
- 리스트 타입의 sort 메서드는, key 함수가 반환하는 값이 서로 같은 경우, 리스트에 들어 있던 원래 순서를 그대로 유지해준다.
power_tools.sort(key=lambda x: x.name)
power_tools.sort(key=lambda x: x.weight,
reverse=True)
print(power_tools)