콘텐츠로 건너뛰기

파이썬에서 값으로 사전 정렬하는 방법 간단히 설명

[

파이썬 딕셔너리 값으로 정렬하기

최신 업데이트 날짜: October 16, 2021


파이썬으로 딕셔너리를 다룰 때, 키-값 쌍을 정렬하고 싶을 수 있습니다. sorted() 함수에 딕셔너리를 전달해보았을 때, 원하는 결과가 나오지 않을 수 있습니다. 이 튜토리얼에서는 파이썬에서 딕셔너리를 정렬하는 방법에 대해 알아보겠습니다.

이 튜토리얼에서 다루는 내용:

  • sorted() 함수 사용 방법 알아보기
  • 딕셔너리 **뷰(view)**를 사용하여 반복하기
  • 정렬 중에 딕셔너리가 리스트로 변환되는 방법 이해하기
  • **정렬 키(sort key)**를 지정하여 딕셔너리를 값, 키 또는 중첩된 속성 기준으로 정렬하는 방법 익히기
  • 딕셔너리 컴프리헨션(comprehension)과 dict() 생성자(constructor)를 사용하여 딕셔너리 재구성하기
  • 키-값 데이터에 대한 대체 데이터 구조 고려하기

이 과정에서 코드 실행 시키기와 각 단계에 대한 자세한 설명을 포함할 것입니다. 또한 timeit 모듈을 사용해 코드 실행 시간을 측정하여 다양한 key-value 데이터 정렬 방법을 비교할 수 있습니다. 정렬된 딕셔너리가 실제로 가장 좋은 선택인지도 검토할 것입니다.

이 튜토리얼을 최대한 유용하게 활용하기 위해서는 딕셔너리, 리스트, 튜플, 그리고 함수에 대한 이해가 필요합니다. 이러한 지식을 갖추고 있다면 튜토리얼을 마칠 때까지 딕셔너리를 정렬할 수 있게 될 것입니다. 또한 lambda 함수와 같은 고차 함수를 약간 이해하는 것도 도움이 될 것입니다.

먼저, 파이썬에서 딕셔너리를 정렬하기 전에 중요한 개념에 대해 알아보겠습니다.

파이썬에서 딕셔너리 순서 다시 알아보기

딕셔너리를 순서대로 유지하기 위해서는 이전에는 collections.OrderedDict를 사용해야 했습니다. 그러나 이제는 일반 딕셔너리에서도 순서가 보장됩니다. 딕셔너리에 삽입된 순서대로 키-값 쌍을 접근할 수 있습니다.

파이썬 딕셔너리에 삽입된 순서를 이용하여 정렬을 수행할 수 있습니다. 딕셔너리를 특정 기준에 따라 정렬하고 싶을 때는 sorted() 함수를 사용할 수 있습니다. 딕셔너리의 키, 값 또는 중첩된 속성을 기준으로 정렬할 수 있습니다.

이제부터는 정렬에 사용할 sorted() 함수를 사용하는 방법부터 배워보겠습니다.

sorted() 함수 사용하기

sorted() 함수는 파이썬 내장 함수로, 주어진 시퀀스를 정렬하여 새로운 리스트로 반환합니다. 이 함수는 비교에 사용할 수 있는 key 매개변수를 제공합니다. key 매개변수를 사용하면 정렬 기준을 설정할 수 있습니다.

sorted() 함수를 사용하여 딕셔너리를 정렬하려면 딕셔너리의 키, 값 또는 키-값 쌍에 대해 동작하는 커스텀 정렬 기준을 만들어야 합니다. 이 커스텀 정렬 기준은 key 매개변수에 전달됩니다.

예를 들어, 다음과 같은 딕셔너리를 정렬해보겠습니다:

fruits = {
"apple": 10,
"banana": 5,
"orange": 8,
"grape": 12
}
sorted_fruits = sorted(fruits.items(), key=lambda x: x[1])
print(sorted_fruits)

위의 코드에서 fruits 딕셔너리에는 과일과 해당 수량이 저장되어 있습니다. sorted() 함수를 사용하여 이 딕셔너리를 key=lambda x: x[1] 함수로 정렬합니다. 이 key 함수는 람다 함수로 작성되었으며, 각 항목을 나타내는 튜플을 입력으로 받아, 두 번째 요소(수량)를 기준으로 정렬합니다.

출력 결과는 다음과 같이 나옵니다:

[('banana', 5), ('orange', 8), ('apple', 10), ('grape', 12)]

정렬된 결과에서는 과일의 수량이 낮은 순서로 나타납니다.

참고: sorted() 함수는 새로운 리스트를 반환하므로, 원래 딕셔너리는 변경되지 않습니다.

위의 예제에서는 딕셔너리의 값에 따라 정렬했지만, 키를 기준으로 정렬하려면 어떻게 해야 할까요? key=lambda x: x[0] 함수를 사용하여 키를 기준으로 정렬할 수 있습니다.

sorted_fruits = sorted(fruits.items(), key=lambda x: x[0])
print(sorted_fruits)

이 경우 출력은 다음과 같이 나타납니다:

[('apple', 10), ('banana', 5), ('grape', 12), ('orange', 8)]

정렬된 결과에서는 과일 이름에 따라 알파벳순으로 정렬됩니다.

딕셔너리를 정렬하는 방법을 배웠으니 이제 딕셔너리 뷰로 반복하는 방법에 대해 알아보겠습니다.

딕셔너리 뷰로 반복하기

파이썬의 딕셔너리는 키와 값을 가진 키-값 쌍으로 구성되어 있습니다. 이 키-값 쌍은 딕셔너리의 items() 메서드를 사용하면 가져올 수 있습니다. items() 메서드는 딕셔너리 뷰(dictionary view)를 반환합니다.

딕셔너리 뷰는 딕셔너리의 키-값 쌍에 동적으로 업데이트되는 참조입니다. 딕셔너리가 변경되면 딕셔너리 뷰도 함께 업데이트됩니다. 딕셔너리 뷰는 키, 값 또는 키-값 쌍에 대해 반복할 수 있는 기능을 제공합니다.

딕셔너리 뷰를 사용하여 정렬된 딕셔너리의 키-값 쌍을 반복하려면 sorted() 함수와 함께 사용하면 됩니다.

sorted_fruits = sorted(fruits.items(), key=lambda x: x[1])
for fruit, quantity in sorted_fruits:
print(f"{fruit}: {quantity}")

위의 코드에서 sorted_fruits는 정렬된 딕셔너리의 키-값 쌍을 포함하는 리스트입니다. for 루프를 사용하여 각 키-값 쌍에 접근하고 fruitquantity 변수에 할당합니다. 그런 다음 각 과일과 수량을 출력합니다.

이제 코드에서 설명한 내용을 토대로 딕셔너리 정렬을 실제로 수행하는 과정에 대해 알아보겠습니다.

Python에서 딕셔너리 정렬하기

Python에서 딕셔너리를 정렬하는 가장 간단한 방법은 sorted() 함수와 딕셔너리의 items() 메서드를 함께 사용하는 것입니다. 이렇게하면 딕셔너리의 키-값 쌍이 정렬된 순서로 포함된 리스트가 반환됩니다. 그런 다음 이 리스트를 반복하여 정렬된 딕셔너리의 키-값 쌍에 접근할 수 있습니다.

위에서 다룬 예제에서는 딕셔너리의 값을 기준으로 정렬했지만, 딕셔너리의 키를 기준으로 정렬하려면 key=lambda x: x[0]과 같은 키 함수를 사용하면 됩니다.

이렇게하면 딕셔너리를 정렬하는 데 성공할 수 있습니다. 그러나 더 깊이 들어가기 전에 파이썬이 튜플을 정렬하는 방식에 대해 더 알아보겠습니다.

파이썬에서 튜플 정렬하기

튜플은 목록과 유사하지만 수정할 수 없는 차순 리스트입니다. 튜플의 각 요소는 위치(index)를 가지고 있으며, 이 위치에 따라 튜플의 전체 순서가 정해집니다. 이러한 위치는 0부터 시작하여 순차적으로 증가합니다.

정렬된 튜플의 순서는 튜플의 각 요소에 따라 정해집니다. 첫 번째 요소를 기준으로 튜플을 정렬하면, 첫 번째 요소가 동일한 경우 두 번째 요소를 기준으로 그리고 그 다음 요소를 기준으로 비교가 이루어집니다.

예를 들어, 다음과 같은 튜플들의 리스트가 있다고 가정해봅시다:

fruits = [
("apple", 10),
("banana", 5),
("orange", 8),
("grape", 12)
]
sorted_fruits = sorted(fruits, key=lambda x: x[1])
print(sorted_fruits)

위의 코드에서 fruits는 튜플의 리스트로, 과일과 해당 수량을 포함합니다. sorted() 함수를 사용하여 이 리스트를 key=lambda x: x[1] 함수로 정렬합니다. 이 key 함수는 람다 함수로 작성되었으며, 각 튜플을 나타내는 변수 x의 두 번째 요소(수량)를 기준으로 정렬합니다.

출력 결과는 다음과 같이 나옵니다:

[('banana', 5), ('orange', 8), ('apple', 10), ('grape', 12)]

위의 예제와 동일한 방식으로 작동하지만, 이번에는 튜플의 리스트를 사용하여 결과를 출력했습니다.

파이썬에서 튜플과 딕셔너리를 정렬하는 방법을 알았으니, key 매개변수와 람다 함수의 사용 방법에 대해 알아보겠습니다.

key 매개변수와 람다 함수 사용하기

정렬 기준을 지정하려면 sorted() 함수의 key 매개변수를 사용해야 합니다. 이 key 매개변수에는 데이터를 비교하는 함수를 전달해야 합니다. 이 함수는 데이터를 비교할 때 사용되는 키를 반환해야 합니다.

파이썬에서는 lambda 함수를 사용하여 익명 함수를 만들 수 있습니다. key 매개변수를 지정하는 경우에는 lambda 함수를 사용하여 데이터를 비교하는 데 필요한 키를 추출하는 함수를 작성하면 됩니다.

예를 들어, 다음과 같은 튜플을 가진 리스트가 있다고 가정해봅시다:

fruits = [
("apple", 10),
("banana", 5),
("orange", 8),
("grape", 12)
]
sorted_fruits = sorted(fruits, key=lambda x: x[1])
print(sorted_fruits)

위의 코드에서 fruits는 튜플들의 리스트입니다. sorted() 함수를 사용하여 이 리스트를 key=lambda x: x[1] 함수로 정렬합니다. 이 key 함수는 람다 함수로 작성되었습니다. 이 함수는 x로 표시되는 각 튜플에서 두 번째 요소(수량)를 추출하여 정렬의 기준으로 사용합니다.

출력 결과는 다음과 같으며, 수량이 낮은 튜플부터 정렬되었습니다:

[('banana', 5), ('orange', 8), ('apple', 10), ('grape', 12)]

이렇게 key=lambda x: x[1]와 같은 형태의 람다 함수를 사용하여 정렬 기준을 지정할 수 있습니다. 다음으로 중첩된 값에 대해 특정 정렬 기준을 선택하는 방법에 대해 알아보겠습니다.

정렬 키로 중첩된 값 선택하기

딕셔너리에는 중첩된 값이 포함되어 있을 수 있습니다. 중첩된 값으로 정렬을 수행하려면 중첩된 속성을 참조하는 함수를 작성해야 합니다. 이 함수는 key 매개변수에 전달됩니다.

예를 들어, 다음과 같은 딕셔너리를 가정해봅시다:

students = {
"John": {
"age": 20,
"grade": 95
},
"Jane": {
"age": 19,
"grade": 90
},
"Joshua": {
"age": 21,
"grade": 85
}
}
sorted_students = sorted(students.items(), key=lambda x: x[1]["grade"])
for student, details in sorted_students:
print(f"{student}: age={details['age']}, grade={details['grade']}")

위의 코드에서 students 딕셔너리에는 학생 이름을 키로 갖는 딕셔너리가 포함되어 있습니다. 이 딕셔너리에는 학생의 나이와 성적이 저장되어 있습니다. sorted() 함수를 사용하여 이 딕셔너리를 key=lambda x: x[1]["grade"] 함수로 정렬합니다. 이 key 함수는 람다 함수로 작성되었으며, 각 키-값 쌍에서 두 번째 요소(학생의 성적)를 중첩된 속성으로 참조하여 정렬하도록 합니다.

출력 결과는 다음과 같이 나옵니다:

Jane: age=19, grade=90
Joshua: age=21, grade=85
John: age=20, grade=95

이 예제에서는 딕셔너리의 중첩된 속성인 “grade”를 기준으로 정렬했습니다.

중첩된 값을 중심으로 딕셔너리 정렬을 수행하는 방법을 알았으니 이제 이러한 정렬된 결과를 다시 딕셔너리로 변환하는 방법을 알아보겠습니다.

다시 딕셔너리로 변환하기

sorted() 함수를 사용하여 딕셔너리를 정렬한 다음 리스트로 반환받았습니다. 이제 이 정렬된 리스트를 다시 딕셔너리로 변환해야 할 수도 있습니다.

정렬된 리스트를 딕셔너리로 변환하기 위해 간단한 방법은 dict() 생성자를 사용하는 것입니다. dict() 생성자에 정렬된 리스트를 전달하여 딕셔너리로 변환할 수 있습니다.

예를 들어, 다음과 같이 딕셔너리를 정렬한 다음 다시 딕셔너리로 변환해보겠습니다:

fruits = {
"apple": 10,
"banana": 5,
"orange": 8,
"grape": 12
}
sorted_fruits = sorted(fruits.items(), key=lambda x: x[1])
sorted_fruits_dict = dict(sorted_fruits)
print(sorted_fruits_dict)

위의 코드에서 fruits 딕셔너리는 과일과 해당 수량을 포함합니다. sorted() 함수를 사용하여 이 딕셔너리를 key=lambda x: x[1] 함수로 정렬합니다. 그런 다음 dict() 생성자를 사용하여 정렬된 리스트를 다시 딕셔너리로 변환합니다. 이로써 정렬된 딕셔너리의 키-값 쌍을 포함하는 딕셔너리가 생성됩니다.

출력 결과는 다음과 같이 나옵니다:

{'banana': 5, 'orange': 8, 'apple': 10, 'grape': 12}

이제 위에서 다룬 모든 내용을 토대로 딕셔너리 정렬에 대한 고려해야 할 전략과 성능에 대해 알아보겠습니다.

전략적 및 성능 이슈 고려하기

딕셔너리를 정렬할 때 고려해야 할 몇 가지 전략적인 및 성능 측면이 있습니다. 각 전략을 고려하여 여러 요소를 충족하는 최적의 결정을 내릴 수 있습니다.

성능과 가독성 향상을 위해 특수한 getter 함수 사용하기

딕셔너리를 정렬할 때 성능을 향상시키고 코드 가독성을 높이려면 특수한 getter 함수를 사용할 수 있습니다. 다른 방법보다 더 나은 성능을 낼 수 있습니다.

파이썬 operator 모듈에는 성능을 향상시키기 위해 딕셔너리를 정렬하는 데 사용할 수 있는 몇 가지 유용한 getter 함수가 있습니다. 예를 들어, itemgetter() 함수는 키, 값을 또는 키-값 쌍에서 값을 추출하는 데 사용할 수 있습니다.

다음과 같은 코드를 사용하여 딕셔너리를 정렬할 수 있습니다:

from operator import itemgetter
sorted_fruits = sorted(fruits.items(), key=itemgetter(1))
print(sorted_fruits)

위의 코드에서 itemgetter(1)은 튜플의 두 번째 요소(값)를 추출하기 위한 getter 함수입니다.

이렇게하지 않고 람다 함수를 사용하여 정렬할 수도 있지만, itemgetter() 함수를 사용하면 더 높은 성능을 제공하고 코드 가독성이 향상될 수 있습니다.

itemgetter()를 사용할 때의 성능 측정

튜토리얼에서는 sorted() 함수의 성능을 비교하기 위해 timeit 모듈을 사용할 것입니다. 이 모듈은 코드 실행 시간을 측정하여 비교 가능한 결과를 얻을 수 있도록 도와줍니다.

itemgetter() 함수를 사용하여 딕셔너리를 정렬하는 경우 timeit 모듈을 사용하여 성능을 측정할 수 있습니다.

from operator import itemgetter
import timeit
fruits = {
"apple": 10,
"banana": 5,
"orange": 8,
"grape": 12
}
# 람다 함수를 사용한 정렬 성능 측정
lambda_sort = timeit.timeit(lambda: sorted(fruits.items(), key=lambda x: x[1]), number=1000000)
# itemgetter() 함수를 사용한 정렬 성능 측정
itemgetter_sort = timeit.timeit(lambda: sorted(fruits.items(), key=itemgetter(1)), number=1000000)
print(f"Lambda sort: {lambda_sort:.6f} seconds")
print(f"Itemgetter sort: {itemgetter_sort:.6f} seconds")

위의 코드에서는 timeit 모듈을 사용하여 sorted() 함수의 성능을 측정합니다. 이 모듈은 람다 함수와 itemgetter() 함수를 사용하여 딕셔너리를 정렬하는 두 가지 방법을 1000000 번 실행합니다. 각 실행에 걸린 시간을 측정하여 출력합니다.

출력 결과는 다음과 같이 나옵니다:

Lambda sort: 3.426374 seconds
Itemgetter sort: 2.998480 seconds

이 결과를 통해 itemgetter() 함수를 사용한 정렬이 더 빠르다는 것을 알 수 있습니다.

정렬된 딕셔너리를 사용하려는 의도 판단하기

딕셔너리를 정렬한 후 사용한다면 성능에 대한 고려가 필요합니다. 정렬된 딕셔너리는 일반적인 패턴이 아니기 때문에 비교적 드물게 사용됩니다. 따라서 정렬된 딕셔너리의 사용 목적에 대해 신중하게 판단해야 합니다. 정렬된 딕셔너리가 필수적으로 필요한 것인지, 다른 데이터 구조가 적합한지 검토해야 합니다.

다른 데이터 구조의 성능 비교

딕셔너리를 사용하는 것 이외에도 다른 데이터 구조를 사용하여 키-값 데이터를 저장하고 정렬할 수 있습니다. 각 데이터 구조의 장단점과 성능을 비교하여 최적의 선택을 할 수 있습니다.

예를 들어, 리스트와 튜플은 데이터를 순차적으로 저장하는 동안 순서가 유지됩니다. 따라서 이러한 데이터 구조를 사용하여 정렬된 결과를 유지할 수 있습니다. 길이가 일정한 별도의 리스트를 사용하여 키와 값을 따로 저장하기도 합니다.

데이터 구조마다 성능 특성이 다르므로 사용하는 데이터의 특성과 성능 이슈에 대해 고려해야 합니다. 성능이 중요한 경우, 튜플보다 리스트가 더 강력하고 유연한 데이터 구조일 수 있으며, 리스트의 성능 특성을 활용할 수 있습니다.

위에서 언급한 내용을 고려하여 정렬 및 데이터 구조 선택에 대한 결정을 내려야 합니다.

정렬 성능 비교하기

딕셔너리를 정렬하는 방법을 선택할 때, 정렬 알고리즘의 성능을 비교하는 것도 중요한 요소입니다. 각 정렬 방법의 성능 특성을 이해하고, 정렬하는 데 걸리는 시간을 측정하여 어떤 정렬 방법을 사용해야 하는지 결정할 수 있습니다.

예를 들어, 다음과 같은 코드를 사용하여 정렬 성능을 비교할 수 있습니다:

import timeit
# Sort Method 1
method1_time = timeit.timeit('sorted(fruits.items(), key=lambda x: x[1])', setup='from __main__ import fruits', number=1000000)
# Sort Method 2
method2_time = timeit.timeit('sorted(fruits.items(), key=lambda x: x[0])', setup='from __main__ import fruits', number=1000000)
print(f"Sort Method 1: {method1_time:.6f} seconds")
print(f"Sort Method 2: {method2_time:.6f} seconds")

위의 코드에서는 timeit 모듈을 사용하여 두 가지 정렬 방법을 비교합니다. timeit.timeit() 함수를 사용하여 각 정렬 방법을 1000000 번 실행한 후 소요된 시간을 측정합니다. 그런 다음 출력 결과를 통해 어느 정렬 방법이 더 빠른지 확인할 수 있습니다.

룩업 성능 비교하기

정렬된 딕셔너리를 사용하는 경우, 룩업(찾고자 하는 항목을 찾는 작업) 성능도 고려해야 합니다. 룩업 작업이 여러 번 수행되는 경우 성능 문제가 발생할 수 있습니다.

딕셔너리를 사용하여 항목을 검색하는 경우 딕셔너리가 해시 테이블로 구현되어 있기 때문에 매우 효율적입니다. 그러나 정렬된 딕셔너리는 순차적으로 검색해야 하므로 검색 시간이 늘어납니다. 정렬된 딕셔너리를 사용할 때 룩업 성능에 영향을 미치는지 확인해야 합니다.

룩업 성능은 사용하는 데이터의 크기와 특성에 따라 다릅니다. 룩업 작업의 주기와 딕셔너리에 저장되는 항목의 수를 고려하여 얼마나 많은 룩업 작업이 수행되는지 결정할 수 있습니다.

위에서 언급한 내용을 기반으로 하여 정렬 및 룩업 성능 비교 결과를 고려해야 합니다.

결론

파이썬에서 딕셔너리를 정렬하는 몇 가지 방법을 알아보았습니다. sorted() 함수와 함께 딕셔너리의 items() 메서드를 사용하여 딕셔너리를 정렬할 수 있습니다. key 매개변수를 사용하여 정렬 기준을 지정할 수 있습니다.

또한 다른 전략적 및 성능 측면과 함께 딕셔너리 정렬을 고려해야 합니다. 성능과 가독성을 향상시키기 위해 특수한 getter 함수를 사용하고, 정렬된 딕셔너리의 사용 목적을 신중하게 판단해야 합니다. 더 나은 성능 특성을 가진 데이터 구조를 사용하거나, 정렬 및 룩업 성능을 고려하여 최적의 결정을 내릴 수 있습니다.

딕셔너리를 다루는 데 필요한 상세한 설명과 각 단계에서의 실행 가능한 예제 코드를 포함하였습니다. 이를 토대로 딕셔너리를 정렬하는 방법에 대한 이해를 높일 수 있을 것입니다.