python sorted 에 대해서.
sorted 에 대해서 질문을 받았고 잘 대답을 하지 못해서 복기차원에서 이 글을 쓴다. 대부분의 내용은 Sorting HOW TO 라는 글에서 가져왔음을 밝힌다.
list.sort() vs sorted()
list.sort()
는 리스트 내부에서 정렬된다. 그에 비해sorted()
는 정렬된 값을 돌려준다. 그렇기 때문에 원래 값을 유지하면서 정렬된 결과를 얻고 싶다면sorted()
를 사용하면 된다.list.sort()
는 값을 돌려주지 않기 때문에 받게 되면 None 을 받게 된다.list.sort()
는 리스트 형에 한해서만 동작하지만,sorted()
는 iterable(순회가능) 한 자료형에 대해서 동작한다.
>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]
Key Functions
- 둘 다
key
파라미터를 가지고 있는데, 비교를 하는 기준으로 사용된다.
>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
key
파라미터는 함수여야 하고, 하나의 입력값과 반환값을 가진다.- key 파라미터로 전달된 함수는 입력 레코드마다 한번씩 호출되어진다.
- 일반적 패턴은 클래스나 복잡한 객체들을 정렬할 때 사용한다.
>> student_objects = [
... Student('john', 'A', 15),
... Student('jane', 'B', 12),
... Student('dave', 'B', 10),
... ]
>>> sorted(student_objects, key=lambda student: student.age) # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
Operator Module Functions
- 파이썬에서 좀더 편하게 사용할수 있는 접근자 함수를 제공하고 있음.
- operator 모듈의
itemgetter()
,attrgetter()
,methodcaller()
>>> from operator import itemgetter, attrgetter
>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
위의 예제에서도 볼 수 있듯이
itemgetter()
,attrgetter()
는 복잡한 자료형내(객체나)에 있는 특정 값을 가져오는 함수들이고, 하나 뿐만 아니라 여러개의 값을 가져오게 할 수도 있다.methodcaller()
는 말 그대로 어떤 메소드를 호출해 주는 역할을 하는 함수이다.
>>> from operator import methodcaller
>>> f = methodcaller('name')
>>> class B():
... def name(self):
... print("test")
...
>>> b = B()
>>> f(b)
test
Sort Stability and Complex Sorts
- 정렬은 stable 을 지원한다.
- stable, unstable 정렬은 같은 키의 기준일떄 기존의 순서를 보존하느냐의 차이이다.
>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
>>> sorted(data, key=itemgetter(0))
[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]
위의 코드를 보면
itemgetter(0)
를 통해서 키 값을 지정하고 있는데, blue 라는 값이 같은키인데, 처음 들어가 있던 순서('blue', 1), ('blue', 2)
가 정렬후에도 보장되는 것을 볼 수 있다.내부적으로 Hybrid Algorithm 중 하나인 Timsort 알고리즘을 사용하고 있고 이 알고리즘은 데이터셋내 이미 존재하는 순서를 이용하는 이점을 가지고 있다.
Reference