[Python] .sort(), sorted(), 다중 조건

파이썬에서,

리스트를 정렬할 때 사용하는 sort함수와 sorted함수의 차이점 에 대해서 자세히 알아보자.

 

 

.sort() vs sorted()

  • .sort함수는 리스트명.sort() 형식으로 "리스트형의 메서드"이며 리스트 원본 값을 직접 변경.

  • sorted함수는 sorted(리스트명) 형식으로 "내장 함수"이며 리스트 원본 값은 그대로 두고

    정렬된 값을 반환한다.

 

 

.sort()

  • .sort()는 기본적으로 오름차순을 기본 값으로 가진다.
  • list.sort()함수의 리턴 값은 존재하지 않아서 출력하게 되면 None이 출력 된다.
  • list자체의 값을 바꿔주고 list의 메서드 이다.
>>> a=[3,5,2,2,4,1,10,9]
>>> b=a.sort()
>>> print(a)
[1, 2, 2, 3, 4, 5, 9, 10]
>>> print(b)
None

 

 

sorted()

  • 기본적으로 오름차순이 기본 값이다.
  • 인자로 문자열, 튜플, 딕셔너리, 제너레이터 등 반복 가능한 객체를 정렬하여 반환한다.
  • 원본 리스트의 값은 유지 되고, 함수의 리턴 값으로 정렬된 리스트가 반환된다.
>>> a=[3,5,2,2,4,1,10,9]
>>> b=sorted(a)
>>> print(a)
[3, 5, 2, 2, 4, 1, 10, 9]
>>> print(b)
[1, 2, 2, 3, 4, 5, 9, 10]

 

 

Key Functions

  • 둘 다 key인자를 가지고 있고, 비교하는 기준으로 사용한다.
  • 인자 없이 그냥 sorted()만 쓰면, 리스트 아이템의 각 요소를 순서대로 정렬한다.
>>> a = [(1, 2),(0, 1),(5, 1),(-1,1),(5, 2),(3,4),(3, 0)]
>>> sorted(a)
[(-1, 1), (0, 1), (1, 2), (3, 0), (3, 4), (5, 1), (5, 2)]

 

 

  • key인자에 함수를 넘겨주면 해당 함수의 반환 값을 비교하여 순서대로 정렬한다.
  • key인자로 전달된 함수는 입력 아이템마다 한번 씩 호출되어진다.
>>> sorted(a, key = lambda x : x[0])
[(-1, 1), (0, 1), (1, 2), (3, 4), (3, 0), (5, 1), (5, 2)]
>>> sorted(a, key = lambda x : x[1])
[(3, 0), (0, 1), (5, 1), (-1, 1), (1, 2), (5, 2), (3, 4)]

 

  • 아이템의 첫 번째 인자를 기준으로 내림차순으로 먼저 정렬하고,

    두 번째 인자를 기준으로 오름차순으로 정렬하게 하려면, 다음과 같이 사용한다.

  • 비교할 아이템의 요소가 복수 개일 경우, 튜플로 그 순서를 내보내주면 된다.

    • ex. sorted(e, key = lambda x : (-x[0], x[1]))
    • -를 붙이면, 현재 정렬 차순과 반대로 하게 된다
>>> sorted(a,key=lambda x: (-x[0],x[1]))
[(5, 1), (5, 2), (3, 0), (3, 4), (1, 2), (0, 1), (-1, 1)]

 

 

  • 일반적인 패턴은 클래스나 복잡한 객체들을 정렬할 때 사용한다.
>>> student_objects=[
...    Student('bro','A',20),
...    Student('grammer','B',12),
...    Student('james','C',18),
...    Student('linda','B',18),
...]
>>>sorted(student_objects,key=lambda student: student.age)
[('grammer', 'B', 12), ('james', 'C', 18), ('linda', 'B', 18), ('bro', 'A', 20)]

 

 

Operator Module Functions

  • 파이썬에서 더 편리하게 사용할 수 있는 접근자 함수를 제공한다.
  • operator모듈의 itemgetter(),attrgetter()
  • 인덱스로 가지고 오는 변수는itemgetter()함수 사용, 객체의 속성을 가지고 오는 함수는 attrgetter()사용
  • 하나 뿐만 아니라 여러 개의 값을 가지고 비교 할 수 있다.
>>> student_tuples=[
...    ('bro','A',20),
...    ('grammer','B',12),
...    ('james','C',18),
...    ('linda','B',18),
... ]
>>> from operator import itemgetter, attrgetter
>>> sorted(student_tuples, key=itemgetter(0)) # lambda x: x[0]과 같은 정렬.
[('bro', 'A', 20), ('grammer', 'B', 12), ('james', 'C', 18), ('linda', 'B', 18)]
>>> sorted(student_objects, key=attrgetter('age')) #lambda student: student.age와 같음.
[('grammer', 'B', 12), ('james', 'C', 18), ('linda', 'B', 18), ('bro', 'A', 20)]
>>> sorted(student_tuples, key=itemgetter(1,2))
[('bro', 'A', 20), ('grammer', 'B', 12), ('linda', 'B', 18), ('james', 'C', 18)]
>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('bro', 'A', 20), ('grammer', 'B', 12), ('linda', 'B', 18), ('james', 'C', 18)]

 

 

Sort Stability

  • 정렬은 stable sort를 하게 된다.
  • stable sort: 키의 우선순위가 같을 때 기존 list의 순서를 보존한다.
  • unstable sort: 키의 우선순위가 같을 때 기존 list의 순서를 보존하지 않는다.
>>> tmp = [(21,'Junkyu'),(21,'Dohyun'),(20,'Sunyoung')]
>>> sorted(tmp,key= lambda x: x[0])
[(20, 'Sunyoung'), (21, 'Junkyu'), (21, 'Dohyun')]
  • 코드를 보면 x[0]를 통해서 키 값을 지정하고 21이라는 같은 키 값을 가지는

    튜플 (21,'Junkyu'),(21,'Dohyun')가 존재하는데 이 값의 순서가 정렬 후에도 보존이 된다.

  • 파이썬에서는 내부적으로 Hybrid Algorithm중 하나인 Timsort알고리즘을 사용하고 있고 이 알고리즘은 데이터 셋 내 이미 존재하는 순서를 이용하는 이점을 가지고 있다.

  • 덧붙여 말하자면 이게 당연하다고 생각할 수 있지만 내장 함수로 Stable sort를 지원 안 하는 언어도 있고, 쓰는 정렬 알고리즘에 따라서 키 값의 우선순위가 같다면 아이템들의 순서는 랜덤하게 배정 받게 된다.

 

Reference

- http://blog.weirdx.io/post/50236

 

+ Recent posts