오히려 좋아..

상황이 나쁘게만 흘러가는 것 같을 때 외쳐보자.. .

궁금한 마음으로 포트폴리오 보기

Language/Python

파이썬 sorted() 함수 사용방법

junha6316 2020. 6. 2. 11:48

목차

------------------------------------------------------------------------------------------------------------------------------

1. sorted() 기본

2. sorted(iterable, key= )

  ① 단일 인자를 취하고 정렬 목적으로 사용할 키를 반환하는 함수

   어트리뷰트를 갖는 객체

  operator 모듈 함수를 이용한 itemgetter(),attrgetter(),methodcaller()

3. 복잡한 정렬

--------------------------------------------------------------------------------------------------------------------------------

 

정렬은 프로그래밍을 하며 아주 자주 사용되는 방법중 하나이다.

파이썬에서는 딕셔너리, 리스트, 튜플과 같은 자료형의 정렬 방법으로 다음과 같은 방법을 제공한다.

1. list.sort() #리스트를 제자리(in-place)에서 수행하는 메서드
#------------------------------------------------------------------------------
2. sorted() #이터러블로부터 새로운 정렬된 리스트를 만드는 내장함수
#------------------------------------------------------------------------------

이 두 방법의 차이는 다음과 같다.

  list.sort() sorted()
대상 (only) 리스트 반복가능한 모든 자료형
(딕셔너리, 튜플 등등)
In-place
(새로운 변수를 만드는지)
x
(선언되어 있는 리스트에서 정렬 수행)
O
정렬 방식 오름차순(default),
내림차순(reverse =True)
다양한 방식 가능


오늘은 둘 중 새로운 리스트를 만드는 sorted()함수에 대해 알아보도록 하겠다.

1. sorted() 기본

#--------------------------------------------------------------------------------
li =[3,5,7,2,6,9,1]
sorted(li)

>>[1, 2, 3, 5, 6, 7, 9]
#--------------------------------------------------------------------------------
genres=['classic','pop', 'classic', 'classic', 'pop']
sorted(genres)

>>['classic', 'classic', 'classic', 'pop', 'pop']

sorted의 함수는 기본적으로 다음과 같은 형태로 사용할 수 있다.

sorted( 반복가능한 자료형(정렬 대상)) 

즉 괄호 안에 iterable한 자료형을 넣어주면 숫자일 경우 오름차순(기본), 문자일 경우 알파벳 순으로(대문자에 우선순위) 로 정렬된다.

참고로 문자와 숫자가 섞여있는 자료형의 경우 다음과 같은 메세지가 발생한다. 

'<' not supported between instances of 'int' and 'str'

만약 내림차순/ 알파벳 역순을 사용하고 싶다면 reverse =True를 다음과 같이 추가해주면 된다.

li =[3,5,7,2,6,9,1]
sorted(li, reverse=True) #reverse=True를 주면 역순으로 정렬한다

>>[9, 7, 6, 5, 3, 2, 1]

2. sorted(iterable, key= )

sorted()는 key 값을 지정해 정렬기준을 설정할 수 있는데 아래의 경우에는 대소문자를 구분하지 않고 문자열을 알파벳순으로 정렬하기 위해 str.lower를 key로 사용하였다

sorted("This is a test string from Andrew".split(), key=str.lower)

['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']

key로는 다음과 같이 3가지 방법을 이용할 수 있다.

1. 단일 인자를 취하고 정렬 목적으로 사용할 키를 반환하는 함수

2. 객체의 Attribute

3. operator 모듈 함수를 이용한 itemgetter(), attrgetter(), methodcaller()

 

①  단일 인자를 취하고 정렬 목적으로 사용할 키를 반환하는 함수

이렇게 사용하는 경우는 흔치 않기 때문에 몇가지 케이스를 외워두는 것을 추천한다.

str.lower 대소문자를 구분하지 않는 알파벳 순 sorted( list, key=str.lower)
len 문자열의 개수 sorted( list, key=len) #오름차순

다음과 같이 함수를 정의해 사용할 수도 있다. 아래의 예는 5로 나눈 나머지의 크기를 비교해 오름차순으로 정렬하는 예제이다.

def func(x): 
    return x % 5
  
li = [15, 3, 11, 7] 
  
print ("Sorted with key:", sorted(li, key = func)) 

Sorted with key: [15, 11, 7, 3]

 

②  객체의 Attribute

선언된 student_objects 리스트에는 Student 객체를 이용해 생성된 Student 인스턴스들이 존재한다.

아래의 예는 student의 클래스중 Age라는 Attribute를 기준으로 정렬하는 예제이다. 

>> student_objects = [
...     Student('tom', 'A', 15),
...     Student('carolline', 'B', 12),
...     Student('naver', 'B', 10),
... ]

>>> sorted(student_objects, key=lambda student: student.age)
[('naver', 'B', 10), ('carolline', 'B', 12), ('tom', 'A', 15)]

 

③ 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)]

조금 더 편리한 방법으로는 operator 모듈둥 itemgetter(), attrgetter(), methodcaller()가 있다.

itemgetter는 딕셔너리/튜플/리스트(다차원 리스트)등에서 사용 가능하며 정렬 기준을 인덱스를 사용해 정렬 가능하다.

 

itemgetter -tuple, list

가령 첫번째 예에서 student_tuples은 학생들의 정보를 담은 튜플이 있는 리스트이다. key= itemgetter(2)를 사용하면  인덱스가 2인 (실제로는 3번째)원소를 기준으로 오름차순으로 정렬한다.

 

itemgetter - dictionary

참고로 딕셔너리에서 itemgetter()를 사용할 때 key= itemgetter(0)key값을 기준으로 정렬 key= itemgetter(1)value값을 기준으로 정렬 하는 것을 의미한다.

 

3. 복잡한 정렬

인덱스를 여러개 사용해 정렬 할 땐 key 값으로 itemgetter내에 여러 원소나 인덱스를 넣는 방법을 사용하면 된다.

예를 들어 기준이 세번째 원소(index=2)와 첫번째 원소(index=0)라면 key=itemgetter(2,0) 을 넣었다면 먼저 인덱스가 2인 원소를 이용해 정렬한 뒤 같은 값이 있을 경우 그때 인덱스가 0인 원소를 비교해 정렬하는 것을 의미한다.

 

복잡한 정렬을 위해선 "거꾸로 정렬"을 하면된다.  즉 정렬하고 싶은 우선순위와 반대의 순서로 정렬을 시행하면된다.

    genres = sorted(genres, key=operator.itemgetter(2))
    
    genres= sorted(genres, key=operator.itemgetter(1),reverse=True)
    
    genres = sorted(genres, key=operator.itemgetter(0))

위 예에서 genres는 길이가 3인 리스트를 원소로 갖는 2차원 리스트로   [ [1,2,3], [4,5,6] ] 아래와 같이 정렬하고자 한다. 위에서 아래로 우선순위가 있으며 만약 0번째 원소가 동일하다면 첫번째 원소가 큰 순으로 정렬 첫번째 원소가 같다면 두번째 원소가 작은 순으로 정렬하는 방식을 의미한다. 

1. 0번째 원소 오름차순

2. 1번째 원소 내림차순

3. 2번째 원소 오름차순

위에서 배웠던 itemgetter(0,1,2)를 사용하면 genres[1]이 원하는 순서대로 정렬되지 않는다. 이를 해결하기 위해 각 인덱스에 대해 정렬을 따로따로 진행했다. 먼저 인덱스가 [2]인 원소에 대해 정렬을 진행하고 [1]을 역순으로 정렬 그리고 [0]에 대해 정렬하면  genres[0], genres[1](역순), genres[2] 순으로 정렬되어 있는 것을 확인 할 수 있다.

 

 

정렬 HOW TO :https://docs.python.org/ko/3/howto/sorting.html