본문 바로가기

Programming/Python

[Python] sorted() 함수와 list.sort() 메서드 설명 및 비교.

1. sorted() 함수

- `iterable 객체(리스트, 튜플, 문자열 등)`를 정렬하여 `정렬된 새로운 리스트`를 반환하는 내장 함수.

- 쉽게 말해, `iterable`를 받아서 `list`를 반환함.

문법

result = sorted(iterable, key=None, reverse=False)

매개변수

1. iterable (필수)

- 정렬 대상이 되는 iterable 객체.

- ex. `str, list, tuple, dict의 key 등`

2. key (선택, 기본값 : None)

- 정렬 기준을 지정하는 함수.

- 각 요소에 대해 `key`로 전달된 함수가 호출되며, 반환된 값이 정렬 기준이 됨.

- 기본값은 `None`로 이 경우 요소 자체를 기준으로 정렬.

3. reverse (선택, 기본값 : False)

- 정렬 순서를 지정하는 bool 값.

- `reverse = True`로 설정하면 내림차순으로 정렬됨.

- 기본값은 `False`로, 이 경우 오름차순 정렬이 수행됨.

반환값

- `정렬된 새로운 리스트`가 반횐됨.

- 원본 데이터는 변경되지 않음.

예시

1. 기본 예시

sorted([3, 1, 2])  # [1, 2, 3]
sorted("hello")    # ['e', 'h', 'l', 'l', 'o']

2. key 사용

# 기본 정렬 (요소 자체를 기준으로 오름차순)
sorted([3, 1, 2])  # [1, 2, 3]

# 정렬 기준을 절댓값으로 설정
sorted([-5, 3, -2, 7], key=abs)  # [-2, 3, -5, 7]

# 문자열 길이 기준으로 정렬
words = ["apple", "kiwi", "banana"]
sorted(words, key=len)  # ['kiwi', 'apple', 'banana']

# 이는 각각 람다 표현식으로 이렇게도 표현 가능함.
sorted([-5, 3, -2, 7], key=lambda x : abs(x))  # [-2, 3, -5, 7]
words = ["apple", "kiwi", "banana"]
sorted(words, key= lambda x : len(x))  # ['kiwi', 'apple', 'banana']

3. reverse 사용

# 내림차순 정렬
sorted([3, 1, 2], reverse=True)  # [3, 2, 1]

# 길이 기준으로 내림차순 정렬
words = ["apple", "kiwi", "banana"]
sorted(words, key=len, reverse=True)  # ['banana', 'apple', 'kiwi']

4. 반환값

nums = [3, 1, 4]
result = sorted(nums)
print(nums)     # [3, 1, 4] (원본 유지)
print(result)   # [1, 3, 4] (정렬된 새로운 리스트)

5. key에 사용자 지정 함수 사용

1. 절댓값 기준으로 정렬

def by_absolute_value(x):
    return abs(x)

nums = [-5, 3, -2, 7]
result = sorted(nums, key=by_absolute_value)
print(result)  # [-2, 3, -5, 7]

2. 문자열 길이 기준으로 정렬

def by_length(word):
    return len(word)

words = ["apple", "kiwi", "banana"]
result = sorted(words, key=by_length)
print(result)  # ['kiwi', 'apple', 'banana']

6. key에 람다 표현식 사용

위에서 살펴본 함수를 람다 표현식을 사용하면 각각 아래와 같음.

1. 절댓값 기준으로 정렬

nums = [-5, 3, -2, 7]
result = sorted(nums, key=lambda x: abs(x))
print(result)  # [-2, 3, -5, 7]

# 참고로 이는, 아까 그냥 key = abs 로 한 것과 같음.

 

2. 문자열 길이 기준으로 정렬

words = ["apple", "kiwi", "banana"]
result = sorted(words, key=lambda word: len(word))
print(result)  # ['kiwi', 'apple', 'banana']

# 참고로 이는, 아까 그냥 key = len 로 한 것과 같음.

7. 기타 예시

1. 튜플의 두 번째 요소를 기준으로 정렬하되, 값이 같으면 첫 번째 요소를 기준으로 정렬

data = [(1, 3), (4, 1), (2, 2), (3, 1)]
result = sorted(data, key=lambda x: (x[1], x[0]))
print(result)  # [(3, 1), (4, 1), (2, 2), (1, 3)]

두 개 이상의 기준으로 정렬하는 예시였음.

-> 즉, key에 사용하는 (람다) 함수의 반환값이 튜플 형태

2. 대소문자 구분 없이 문자열 정렬

words = ["Banana", "apple", "Cherry"]
result = sorted(words, key=lambda word: word.lower())
print(result)  # ['apple', 'Banana', 'Cherry']

3. 학생 점수 정렬 : 총점 기준, 동점자는 이름순

students = [
    {"name": "Alice", "math": 85, "english": 92},
    {"name": "Bob", "math": 75, "english": 88},
    {"name": "Charlie", "math": 85, "english": 90},
]

# 정렬
result = sorted(
    students,
    key=lambda student: (student["math"] + student["english"], student["name"]),
    reverse=True,
)
print(result)
# [{'name': 'Charlie', 'math': 85, 'english': 90},
#  {'name': 'Alice', 'math': 85, 'english': 92},
#  {'name': 'Bob', 'math': 75, 'english': 88}]

 

8. sorted()는 안정 정렬(stable sort)

- sorted()는 내부적으로 Tim sort로 구현되는데, 이는 stable sort이기에

- 비교 기준이 모두 같으면, 원래의 순서대로 정렬됨.

- 즉, 같은 우선순위를 가지는 것 끼리는 기존의 정렬 순서를 유지함.

data = [(1, 3, 5, 7, 9), (1, 3, 2, 4, 8), (2, 2, 3, 6, 7), (3, 1, 6, 8, 10)]

result = sorted(data, key=lambda x: (x[1], x[0]))

print(result) # [(3, 1, 6, 8, 10), (2, 2, 3, 6, 7), (1, 3, 5, 7, 9), (1, 3, 2, 4, 8)]

 

`(1, 3, 5, 7, 9), (1, 3, 2, 4, 8)`이 원래의 순서를 유지함.

a = ['cde', 'cfc', 'abc', 'czc', 'cac']
result = sorted(a, key = lambda s:(s[0], s[-1]))
print(result) # ['abc', 'cfc', 'czc', 'cac', 'cde']

`'cfc', 'czc', 'cac' 끼리는 원래의 순서를 유지함.

 

https://cuffyluv.tistory.com/125

 

[알고리즘] 안정 정렬 vs 불안정 정렬

https://cuffyluv.tistory.com/123 이전에 작성한 글 참고. data = [(1, 3, 5, 7, 9), (1, 3, 2, 4, 8), (2, 2, 3, 6, 7), (3, 1, 6, 8, 10)]result = sorted(data, key=lambda x: (x[1], x[0]))print(result) # [(3, 1, 6, 8, 10), (2, 2, 3, 6, 7), (1, 3, 5, 7,

cuffyluv.tistory.com

자세한 건 위에 정리한 글 참고.


2. list.sort()

- 리스트 원본 자체를 정렬해 변경하는 리스트 내장 메서드.

- 쉽게 말해, `list`를 받아서 그 자체를 변경함.

문법

list.sort(key=None, reverse=False)

매개변수

1. key (선택, 기본값 : None)

- 정렬 기준을 지정하는 함수.

- 각 요소에 대해 `key`로 전달된 함수가 호출되며, 반환된 값이 정렬 기준이 됨.

- 기본값은 `None`로 이 경우 요소 자체를 기준으로 정렬.

2. reverse (선택, 기본값 : False)

- 정렬 순서를 지정하는 bool 값.

- `reverse = True`로 설정하면 내림차순으로 정렬됨.

- 기본값은 `False`로, 이 경우 오름차순 정렬이 수행됨.

반환값

- 중요!! list.sort()는 반환값이 없음 (반환값 : None)

- 원본 데이터인 리스트가 직접 변경됨.

예시

1. 기본 예시

nums = [3, 1, 2]
nums.sort()
print(nums)  # [1, 2, 3] (원본 리스트가 정렬됨)

2. key 사용

nums = [-5, 3, -2, 7]
nums.sort(key=abs)
print(nums)  # [-2, 3, -5, 7] (절댓값 기준으로 정렬됨)

words = ["apple", "kiwi", "banana"]
words.sort(key=len)
print(words)  # ['kiwi', 'apple', 'banana'] (길이 기준으로 정렬됨)

3. reverse 사용

nums = [3, 1, 2]
nums.sort(reverse=True)
print(nums)  # [3, 2, 1] (내림차순 정렬됨)

words = ["apple", "kiwi", "banana"]
words.sort(key=len, reverse=True)
print(words)  # ['banana', 'apple', 'kiwi'] (길이 기준으로 내림차순 정렬됨)

 

4. key에 사용자 지정 함수 사용

1. 절댓값 기준으로 정렬

def by_absolute_value(x):
    return abs(x)

nums = [-5, 3, -2, 7]
nums.sort(key=by_absolute_value)
print(nums)  # [-2, 3, -5, 7]

2. 문자열 길이 기준으로 정렬

def by_length(word):
    return len(word)

words = ["apple", "kiwi", "banana"]
words.sort(key=by_length)
print(words)  # ['kiwi', 'apple', 'banana']

5. key에 람다 표현식 사용

위에서 살펴본 함수를 람다 표현식을 사용하면 각각 아래와 같음.

1. 절댓값 기준으로 정렬

nums = [-5, 3, -2, 7]
nums.sort(key=lambda x: abs(x))
print(nums)  # [-2, 3, -5, 7]

# 참고로 이는, 아까 그냥 key = abs 로 한 것과 같음.

 

2. 문자열 길이 기준으로 정렬

words = ["apple", "kiwi", "banana"]
words.sort(key=lambda word: len(word))
print(words)  # ['kiwi', 'apple', 'banana']

# 참고로 이는, 아까 그냥 key = len 로 한 것과 같음.

6. 기타 예시

1. 튜플의 두 번째 요소를 기준으로 정렬하되, 값이 같으면 첫 번째 요소를 기준으로 정렬

data = [(1, 3), (4, 1), (2, 2), (3, 1)]
data.sort(key=lambda x: (x[1], x[0]))
print(data)  # [(3, 1), (4, 1), (2, 2), (1, 3)]

두 개 이상의 기준으로 정렬하는 예시였음.

-> 즉, key에 사용하는 (람다) 함수의 반환값이 튜플 형태

2. 대소문자 구분 없이 문자열 정렬

words = ["Banana", "apple", "Cherry"]
words.sort(key=lambda word: word.lower())
print(words)  # ['apple', 'Banana', 'Cherry']

3. 학생 점수 정렬 : 총점 기준, 동점자는 이름순

students = [
    {"name": "Alice", "math": 85, "english": 92},
    {"name": "Bob", "math": 75, "english": 88},
    {"name": "Charlie", "math": 85, "english": 90},
]

# 정렬
students.sort(
    key=lambda student: (student["math"] + student["english"], student["name"]),
    reverse=True,
)
print(students)
# [{'name': 'Charlie', 'math': 85, 'english': 90},
#  {'name': 'Alice', 'math': 85, 'english': 92},
#  {'name': 'Bob', 'math': 75, 'english': 88}]

 

8. sorted()는 안정 정렬(stable sort)

- sorted()는 내부적으로 Tim sort로 구현되는데, 이는 stable sort이기에

- 비교 기준이 모두 같으면, 원래의 순서대로 정렬됨.

- 즉, 정렬 기준이 모두 동일한 요소들은 원래의 순서를 유지함.

data = [(1, 3, 5, 7, 9), (1, 3, 2, 4, 8), (2, 2, 3, 6, 7), (3, 1, 6, 8, 10)]

data.sort(key=lambda x: (x[1], x[0]))

print(data) # [(3, 1, 6, 8, 10), (2, 2, 3, 6, 7), (1, 3, 5, 7, 9), (1, 3, 2, 4, 8)]

 

`(1, 3, 5, 7, 9), (1, 3, 2, 4, 8)`이 원래의 순서를 유지함.

a = ['cde', 'cfc', 'abc', 'czc', 'cac']
a.sort(a, key = lambda s:(s[0], s[-1]))
print(a) # ['abc', 'cfc', 'czc', 'cac', 'cde']

`'cfc', 'czc', 'cac' 끼리는 원래의 순서를 유지함.


3. 정리 및 비교

- 여태 예시들을 보면 알겠지만, 변경할 대상을 첫 매개변수로 쓰냐 아님 메서드의 주체로 쓰냐의 차이지,

- 그 외에 사용 방법이나 테크닉 등은 모두 동일함.

 

- 그러나, 일부 차이점이 있는데

 

- `sorted()`는 원본 객체를 변경하지 않으며, 새로운 리스트를 반환함.

- `list.sort()`는 리스트 자체를 변경하며 반환값이 없음.

=> 둘 다 결국 변환된 결과가 리스트라는 것은 똑같다고 볼 수 있음.

 

- `sorted()`는 `iterable 객체`라면 모두 사용이 가능하나,

- `list.sort()`는 (리스트의 메서드니까 당연히) `list`에만 사용 가능함.

 

- 상황에 맞게 사용하면 될 듯한데,

- 아마 대부분의 상황에서 sorted()를 사용하게 되지 않을까?

- 왜냐면 굳이 원본 리스트를 변경할 필요는 없어보임.

- 원본 리스트는 보험으로 남겨두는 편이 대부분 좋을 테니까.


Ref. 

https://daeun-computer-uneasy.tistory.com/74

https://yummy0102.tistory.com/683

- Chat GPT