[Python] 리스트 정렬

지우개·2024년 3월 6일

Python

목록 보기
1/3

포함내용

  • 1차원 리스트 정렬
  • 2차원 리스트 정렬
  • sort, sorted, reverse, key, lambda 정리

1차원 리스트 정렬

sort 정렬, sorted 정렬

두 함수 모두 디폴트로 동일하게 오름차순 정렬을 수행하고, reverse, key, lambda가 사용 가능하다.

차이점은 sorted의 경우 반환값으로 정렬된 새로운 리스트가 나오지만, sort의 경우 반환값 없이 해당 리스트 자체를 다시 정렬 시킨다.


  • 오름차순 정렬
lst = [3, 5, 4, 2, 1]

# sorted 정렬 사용
sorted_lst = sorted(lst)
print(sorted_lst)

# sort 정렬 사용
lst.sort()
print(lst)

# [1, 2, 3, 4, 5] 정렬된 새로운 리스트
# [1, 2, 3, 4, 5] 해당 리스트 자체를 정렬

디폴트는 오름차순 정렬이지만,
인자로 key, reverse를 넣으면 사용자가 원하는 형태로 정렬이 가능함.


  • 내림차순 정렬(reverse=True 이용)
lst = [3, 5, 4, 2, 1]

# sorted 정렬 사용
sorted_lst = sorted(lst, reverse=True)
print(sorted_lst)

# sort 정렬 사용
lst.sort(reverse=True)
print(lst)

# [5, 4, 3, 2, 1]
# [5, 4, 3, 2, 1]

  • 글자 길이에 따른 정렬(key 이용)
lst = ["three", "five", " four", "two", "one"]

# sorted 정렬 사용
sorted_lst = sorted(lst, key=len)
print(sorted_lst)

# sort 정렬 사용
lst.sort(key=len)
print(lst)

# ['two', 'one', 'five', 'three', ' four']
# ['two', 'one', 'five', 'three', ' four']

len 함수 결과에 따라 가장 짧은 문자열인 'one'이 가장 앞으로 오고, 가장 긴 문자열인 'three'가 가장 뒤로 갔음.


  • 절댓값 기준으로 정렬(key 이용)
lst = [-5, -3, 1, 2, -4]

# sorted 정렬 사용
sorted_lst = sorted(lst, key=abs)
print(sorted_lst)

# sort 정렬 사용
lst.sort(key=abs)
print(lst)

# [1, 2, -3, -4, -5]
# [1, 2, -3, -4, -5]

  • 절대값 내림차순으로 정렬(reverse와 key 동시에 사용 가능)
lst = [-5, -3, 1, 2, -4]

# sorted 정렬 사용
sorted_lst = sorted(lst, reverse=True, key=abs)
print(sorted_lst)

# sort 정렬 사용
sort(reverse=True, key=abs)
print(lst)

# [5, 4, 3, 2, 1]
# [5, 4, 3, 2, 1]

key를 사용하여 정렬 기준을 2개 이상 하고 싶을 때는 어떻게 하면 좋을까?

만약 문자열을 길이순으로 정렬하는데, 같은 길이에서는 사전순으로 정리하고 싶을 경우

원본 리스트를 길이순으로 정렬하고, 정렬한 리스트를 다시한번 사전순으로 정렬하면 되지않을까?

정렬해야할 리스트

lst = ["apple", "abc", "android", "cherry", "aaa", "app", "banana"]

먼저 길이순으로 정렬한다.

lst.sort(key=len)

그리고 사전순으로 정렬한다.

lst.sort()

결과는
['aaa', 'abc', 'app', 'apple', 'banana', 'cherry', 'android']
처럼 나오지 않고,

['aaa', 'abc', 'android', 'app', 'apple', 'banana', 'cherry']
위처럼 나온다.

즉, 문자열 길이순으로 정렬하고, 사전순으로 정렬하면 각각 개별로 정렬하는 것이기 때문에 정렬해 놓은 것이 깨진다.

이를 해결하기 위해선 key값에 lambda 적용하여 사용해야한다.

lambda를 이용한 1차원 리스트 조건 정렬

lambda란?
특정 요소를 기준으로 정렬의 기준을 정해줌

lst.sort(key=lambda a:b)
sorted_lst = sorted(lst, key=lambda a:b)

lst

  • 반복할 단위(ex. 리스트)

a

  • 반복할 단위의 각 원소.
  • 입력 인자, 매개변수

b

  • 반복할 단위의 각 원소를 a라고 했을때, a를 사용하여 어떤 기준으로 정렬할지 정해줌.
  • 즉, 특정 요소를 기준으로 정렬의 기준을 정함.
  • 계산하고 반환되는 값이기도 함.
  • 함수식을 적용할 수 있고, 여러 요소를 기준으로 정렬이 가능함.


1차원 리스트에서 lambda의 사용법

  • 오름차순(사전순)으로 정렬
lst = [3, 5, 4, 2, 1]

# sorted 정렬 사용
sorted_lst = sorted(lst, key=lambda x:x)
print(sorted_lst)

# sort 정렬 사용
lst.sort(key=lambda x:x)
print(lst)

# [1, 2, 3, 4, 5]
# [1, 2, 3, 4, 5]

입력인자 x의 뒤에 있는 x는 함수식을 적용하지 않은 상태로 오름차순(사전순) 정렬을 의미


  • 내림차순으로 정렬
lst = [3, 5, 4, 2, 1]

# sorted 정렬 사용
sorted_lst = sorted(lst, key=lambda x:-x)
print(sorted_lst)

# sort 정렬 사용
lst.sort(key=lambda x:-x)
print(lst)

# [5, 4, 3, 2, 1]
# [5, 4, 3, 2, 1]

앞에 -를 붙여주면 내림차순으로 정렬을 의미


  • 문자열 길이 순으로 정렬
lst = ["three", "five", " four", "two", "one"]

# sorted 정렬 사용
sorted_lst = sorted(lst, key=lambda x:len(x))
print(sorted_lst)

# sort 정렬 사용
lst.sort(key=lambda x:len(x))
print(lst)

# ['two', 'one', 'five', 'three', ' four']
# ['two', 'one', 'five', 'three', ' four']
  • 입력인자 x는 lst내의 문자열 하나임 (ex. x='three')
  • 즉, x는 len(x)이기 때문에 5라는 값을 반환하고, 반환된 5는 리스트를 정렬하는데 이용됨.
  • 나머지 "five", " four", "two", "one" 도 4, 4, 3, 3으로 반환되며 반환값들을 이용해 길이순으로 정렬됨.


다시 본론으로 돌아와서...

문자열을 길이순으로 정렬하는데, 같은 길이에서는 사전순으로 정리하고 싶을 경우에는 lambda 정렬 기준을 len(x), x 두 개를 넣으면 됨

lambda를 이용한 1차원 리스트 다중 조건 정렬

사용법
lst.sort(key=lambda x: (1순위 조건, 2순위 조건, ...))
sorted_lst = sorted(lst, key=lambda x: (1순위 조건, 2순위 조건, ...))

lst.sort(key=lambda x:(len(x), x))
sorted_lst = sorted(lst, key=lambda x:(len(x), x))

즉, len(x)를 통해 길이 순서로 정렬하되,
같은 길이가 나온다면, 두번째 비교 방법인 x를 통해서 오름차순(사전순)정렬하라는 뜻임.

key에는 한 개의 정렬 기준만 적용 가능하지만, lambda를 사용하면 두 개의 정렬 기준하나의 정렬 기준인 것처럼 사용이 가능함.


이를 활용한 문제
백준 1181번 - 단어 정렬

import sys

n = int(sys.stdin.readline())
word = []

for i in range(n):
    word.append(input())

word.sort(key=lambda x:(len(x), x))

print(word[0])
for i in range(1, n):
    if word[i-1] == word[i]:
        continue
    print(word[i])

길이가 짧은 순으로 정렬하고, 길이가 같다면 사전순(오름차순)으로 정렬됨.



2차원 리스트 정렬

sort 정렬, sorted 정렬


  • 오름차순(사전순) 정렬
lst = [[1,2],[3,9],[2,7],[2,4],[2,1],[3,1]]

# sorted 정렬 사용
sorted_lst = sorted(lst)
print(sorted_lst)

# sort 정렬 사용
lst.sort()
print(lst)

# [[1, 2], [2, 1], [2, 4], [2, 7], [3, 1], [3, 9]]
# [[1, 2], [2, 1], [2, 4], [2, 7], [3, 1], [3, 9]]

결과를 보면 1번 인덱스의 열에 오름차순 정렬을 하고, 값이 같다면(=조건에 동등하다면) 2번 인덱스 열을 오름차순 정렬함.

1번 인덱스 열에만 오름차순 정렬을 하고 싶다면? (값이 같은 경우는 입력된 순서대로)

key값에 lambda 적용하여 사용해야한다.


lambda를 이용한 2차원 리스트 조건 정렬

sorted_lst = sorted(lst, key=lambda x:x[0])
lst.sort(key=lambda x:x[0])

이렇게 하면 1번 인덱스 열에만 오름차순 정렬이 됨

lst = [[1,2],[3,1],[2,7],[2,4],[2,1],[3,9]]

# sorted 정렬 사용
sorted_lst = sorted(lst, key=lambda x:x[0])
print(sorted_lst)

# sort 정렬 사용
lst.sort(key=lambda x:x[0])
print(lst)

# [[1, 2], [2, 7], [2, 4], [2, 1], [3, 1], [3, 9]]
# [[1, 2], [2, 7], [2, 4], [2, 1], [3, 1], [3, 9]]

이를 활용한 문제
백준 10814번 - 나이순 정렬

key=lambda x:x[0] 사용하지 않은 코드

import sys

n = int(sys.stdin.readline())
info = []

for i in range(n):
    a, b = sys.stdin.readline().split()
    info.append([int(a), b])

info.sort()

for i in info:
    print(*i)

입력

3
21 Junkyu
21 Dohyun
20 Sunyoung

출력

20 Sunyoung
21 Dohyun
21 Junkyu

sort()만 사용하면 나이가 동일한 경우 이름이 사전순으로 정렬되게 됨.


key=lambda x:x[0] 사용한 코드

import sys

n = int(sys.stdin.readline())
info = []

for i in range(n):
    a, b = sys.stdin.readline().split()
    info.append([int(a), b])

info.sort(key=lambda x:x[0])

for i in info:
    print(*i)

입력

3
21 Junkyu
21 Dohyun
20 Sunyoung

출력

20 Sunyoung
21 Junkyu
21 Dohyun

lambda를 통해 정렬하면 입력받은 1번째 인덱스 열을 기준으로만 오름차순 정렬해줌.


lambda를 이용한 2차원 리스트 다중 조건 정렬

사용법 (1차원 리스트 다중 조건 정렬과 동일)
lst.sort(key=lambda x: (1순위 조건, 2순위 조건, ...))
sorted_lst = sorted(lst, key=lambda x: (1순위 조건, 2순위 조건, ...))

1번 인덱스 열은 오름차순으로 정렬하고, 값이 같을 경우(=조건에 동등할 경우) 2번 인덱스 열은 내림차순 정렬하고 싶다면,

lst.sort(key=lambda x:(x[0], -x[1])
sorted_lst = sorted(lst, key=lambda x:(x[0], -x[1]))

위처럼 작성

lst = [[1,2],[3,9],[2,7],[2,4],[2,1],[3,1]]

# sorted 정렬 사용
sorted_lst = sorted(lst, key=lambda x:(x[0], -x[1]))
print(sorted_lst)

# sort 정렬 사용
lst.sort(key=lambda x:(x[0], -x[1]))
print(lst)

# [[1, 2], [2, 7], [2, 4], [2, 1], [3, 9], [3, 1]]
# [[1, 2], [2, 7], [2, 4], [2, 1], [3, 9], [3, 1]]

정렬 기준은 len, abs, 연산 등 다양하게 쓸 수 있음.


관련 백준 문제가 있다면 추가해 보도록 하겠음.

0개의 댓글