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
– Python sorted 알고리즘 Timsort
Array