티스토리 뷰

반응형

파이썬에는 sort()라는 list 자료형 메서드가 존재한다. (sorted 함수는 다른 포스팅으로 다루겠다)

 

자주 사용하지만, 제대로 정리할 필요는 있을 거 같아 이 포스팅으로 정리한다.

thumbnail
sort에 대하여 알아보자.


1. sort()

sort() 메서드는 list 자료형의 메서드중 하나로, list를 제자리에서 정렬을 하는 역할을 한다. 원래의 list를 수정하므로 파괴적 메서드이다.

 

다른 말로, sorting이 가능한 자료형이 list안에 담겨있고, 각 자료형 간 비교가 가능하다면 (쉽게 말해, '<' 을 적용할 수 있으면) sort 메서드를 사용할 수 있다.

 

반대로 말하면, 비교 연산이 가능하지 않거나 비교에 실패하였다면, sort 연산은 실패하게 된다. 이때 실패 지점 이전까지 한 정렬은 수정된 상태로 남는다.

 

1
2
3
4
5
6
7
8
9
10
nums = [13524]
 
nums.sort()
# nums = [1, 2, 3, 4, 5]
 
nums = [1254, (12)]
 
# 오류! tuple과 int형은 비교할 수 없다.
# 다만, tuple형을 비교하기 전까지의 수행된 정렬은 nums에 남아있다.
nums.sort()
cs

sort 메서드의 반환값은 None이다. sort 메서드 자체가 list를 수정하기에, 원래 list가 필요하다면 sorted를 사용해야 한다.

 

1
2
3
4
5
6
nums = [321]
print(nums.sort()) # None을 반환
 
print(nums) 
# 정렬이 수행되었음
# [1, 2, 3]
cs

 


sort 메서드의 기본적으로 두 개의 키워드로 전달할 수 있는 인자가 있다. 두 인자 모두 키워드-전용(keyword-only) 인자이다.

 

sort(*, key = None, reverse = False)

 

1) key = None

key 인자에는 비교 기준을 추가할 수 있다. key에 인자를 넣어준다면 sort가 적용될 list에서 key를 기준으로 정렬을 수행하게 된다. 이때 key는 한 번만 계산하게 된다.

 

기본값은 None으로, python이 기본적으로 제공하는 비교 연산자('<') 순서대로 정렬을 수행한다.

 

다음은 key에 str.lower를 인자로 넘겨준 예시이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
words = ['G''a''C''D''b''E''f']
 
words.sort()
print(words)
 
# ASCII 코드 순서대로 정렬을 수행한다.
# ['C', 'D', 'E', 'G', 'a', 'b', 'f']
 
words.sort(key = str.lower)
print(words)
 
# 모든 문자를 소문자로 바꾸고 정렬을 수행한다.
# ['a', 'b', 'C', 'D', 'E', 'f', 'G']
cs

 

또는 key에 직접 함수를 생성하여 넣거나, 람다식을 활용하여 정렬을 수행할 수 있다. 만약, 여러 기준으로 정렬을 수행하고 싶다면, 람다식을 튜플로 묶거나 별도의 함수를 작성하여 여러 번 정렬을 수행할 수 있다.

 

다음은 key에 람다식을 넣어 활용한 예시이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
tuples = [
    (110049),
    (29765),
    (38530),
    (46230)
]
 
tuples.sort(key = lambda x : x[1])
print(tuples)
 
# tuple의 두 번째 정수를 기준으로 정렬을 수행한다.
# [(4, 62, 30), (3, 85, 30), (2, 97, 65), (1, 100, 49)]
 
tuples.sort(key = lambda x : (x[2], x[1]))
print(tuples)
 
# tuple의 세 번째 정수를 기준으로 정렬을 수행하고,
# 만약 우선순위가 같은 항목이 있다면 두 번쨰 정수를 기준으로 정렬을 수행한다.
# [(4, 62, 30), (3, 85, 30), (1, 100, 49), (2, 97, 65)]
cs

 

혹은, class에서의 attribute를 기준으로 정렬을 수행할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Student:
    def __init__(self, name, grade, age):
        self.name = name
        self.grade = grade
        self.age = age
    def __repr__(self):
        return repr((self.name, self.grade, self.age))
 
students = [
    Student("alice"116),
    Student("bob"320),
    Student("cameron"225)
]
 
students.sort(key = lambda x: x.age)
print(students)
 
# Student 의 age에 따라 정렬 수행
# [('alice', 1, 16), ('bob', 3, 20), ('cameron', 2, 25)]
cs

 

 

혹은, operator 모듈을 활용하면 더욱 쉽고 빠르게 정렬을 수행할 수 있다. 이때 함수 itemgetter(), attrgetter(), methodcaller()를 활용할 수 있다.

 

위에서 사용한 람다식 대신 key에 itemgetter, attrgetter를 활용하면 다음과 같이 작성할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import operator
 
class Student:
    def __init__(self, name, grade, age):
        self.name = name
        self.grade = grade
        self.age = age
    def __repr__(self):
        return repr((self.name, self.grade, self.age))
 
tuples = [
    (110049), (29765),
    (38530), (46230)
]
 
students = [
    Student("alice"116),
    Student("bob"320),
    Student("cameron"225)
]
 
# 위 함수와 아래 함수 모두 같은 역할을 수행하는 함수이다. 
 
#tuples.sort(key = lambda x : x[1])
tuples.sort(key = operator.itemgetter(1))
print(tuples)
 
#tuples.sort(key = lambda x : (x[2], x[1]))
tuples.sort(key = operator.itemgetter(21))
print(tuples)
 
#students.sort(key = lambda x: x.age)
students.sort(key = operator.attrgetter('age'))
print(students)
cs

2) reverse = False

reverse에는 역순 정렬 여부에 관한 인자이다. 만약 False일 경우, 정렬이 오름차순으로 진행된다. 만약 True일 경우, 정렬이 내림차순으로 진행된다.

 

1
2
3
4
5
6
words = ['G''a''C''D''b''E''f']
words.sort(key = str.lower, reverse = True)
print(words)
 
# 역순 정렬이 수행횐다.
# ['G', 'f', 'E', 'D', 'C', 'b', 'a']
cs

2. sort()의 여러 특징

1.

python의 sort는 기본적으로 stable함을 보장한다. 이는, sort가 수행될 때 sort의 기준이 되는 항목 이외의 순서는 기존의 순서가 유지된다는 의미이다.

 

다음 예시에서, list안의 원소에서 정렬되는 기준 이외에는 본래 순서를 유지하는지 확인하여보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
arr = [
    ('a'1),
    ('b'1),
    ('a'2),
    ('b'2),
    ('c'3)
]
 
arr.sort(key = lambda x: x[0])
print(arr)
 
# 기준이 되는 첫번째 원소를 제외하고는 본래 순서 유지
# [('a', 1), ('a', 2), ('b', 1), ('b', 2), ('c', 3)]
cs

 

이때, 두 원소 ('b', 1)과 ('b', 2)의 순서는 유지되고 있음을 확인할 수 있다.

 

2.

sort 메서드를 사용할 때, list 자체 내부에서의 객체에서 사용할 필요는 없다.

 

만약, 다음과 같이 정렬 기준이 dictionary 자료형에 저장되어 있다면, 이를 활용하여 기존 list를 정렬할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
students = ['Alice''Bob''Cameron']
grades = {
    'Alice' : 'F',
    "Bob" : "A",
    "Cameron""C"
}
 
students.sort(key = lambda x : grades[x])
# students.sort(key =grades.__getitem__) 도 가능하다.
print(students)
cs

 

3. 

class 내에서 연산자 오버라이딩을 활용하면 정렬 수행 시 '<'의 우선순위를 정해줄 수 있다.

 

이 경우 별도의 key나 reverse에 인자를 전달할 필요가 없다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Student:
    def __init__(self, name, grade, age):
        self.name = name
        self.grade = grade
        self.age = age
    def __repr__(self):
        return repr((self.name, self.grade, self.age))
 
    def __lt__(self, other):
        return self.age < other.age
 
students = [
    Student("alice"116),
    Student("bob"320),
    Student("cameron"225)
]
 
students.sort()
print(students)
 
# 정렬 순서를 __lt__ ('<')를 오버라이딩하여 정해줌
# [('alice', 1, 16), ('bob', 3, 20), ('cameron', 2, 25)]
cs

 

4.

python 내부에서는 sort의 방법으로 Timsort 알고리즘을 사용한다. (Tim Peters라는 사람이 알고리즘을 개발하였다.)

 


도움이 되었다면 지나가는 길에 하트 하나 눌러주세요, 양질의 글을 쓰는데 하나의 동기부여가 됩니다😍

지적이나 오타 수정 댓글 환영합니다!!

 

 

반응형
댓글
Total
Today
Yesterday
공지사항
최근에 올라온 글
최근에 달린 댓글
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함