키를 기준으로 사전을 정렬하려면 어떻게해야합니까?


939

에서 갈 수있는 좋은 방법이 있을까요 {2:3, 1:89, 4:5, 3:0}{1:89, 2:3, 3:0, 4:5}?
일부 게시물을 확인했지만 모두 튜플을 반환하는 "정렬 된"연산자를 사용합니다.


39
사전은 본질적으로 분류되지 않습니다. 사전을 표시 하는 것도 또 다른 문제입니다. 어쨌든, 당신은 그것을 정말로 분류하기 위해 무엇이 필요합니까?
Karl Knechtel

15
사전은 정렬되지 않습니다. 그들은 단지 없습니다. d가 사전의 이름이라고 가정하고 "for key in sorted (d.keys ())"와 같이 sorted를 사용하여 말한 것과 같은 것을 수행해야하는 경우 요소를 순서대로 살펴 보려면
Ryan Haining

3
@KarlKnechtel-사용 사례는 기본 메뉴가있는 CLI 응용 프로그램이 있고 메뉴 옵션이 사전으로 키로 사용된다는 것입니다. 사용자 안전을 위해 키를 사전 순으로 표시하고 싶습니다.
랜디


4
dicts는 이제 삽입 순서 (파이썬 3.6 이상)로 정렬됩니다. 아래의 일부 답변은 이것을 지적합니다.
matiasg 2016 년

답변:


940

표준 파이썬 사전은 순서가 없습니다. (키, 값) 쌍을 정렬하더라도 dict순서를 유지하는 방식으로 저장할 수는 없습니다 .

가장 쉬운 방법은 OrderedDict요소를 삽입 한 순서를 기억하는를 사용 하는 것입니다.

In [1]: import collections

In [2]: d = {2:3, 1:89, 4:5, 3:0}

In [3]: od = collections.OrderedDict(sorted(d.items()))

In [4]: od
Out[4]: OrderedDict([(1, 89), (2, 3), (3, 0), (4, 5)])

방법 od이 인쇄되는 것을 신경 쓰지 마십시오 . 예상대로 작동합니다.

In [11]: od[1]
Out[11]: 89

In [12]: od[3]
Out[12]: 0

In [13]: for k, v in od.iteritems(): print k, v
   ....: 
1 89
2 3
3 0
4 5

파이썬 3

Python 3 사용자의 경우 .items()대신 다음 을 사용해야합니다 .iteritems().

In [13]: for k, v in od.items(): print(k, v)
   ....: 
1 89
2 3
3 0
4 5

1
나는 이것을 사용하고 작동하며 더 많은 코드와 중복성을 추측하지만 작업을 수행합니다. (d. iterkeys ()) : orderedDict [key] = d [key]
Antony

4
@achrysochoou : 그것이 효과가 있었다면, 그것은 운이 좋았을 것이다. 당신이 들었 듯이, 정규 사전은 정렬 또는 임의의 방식으로 키를 할당하더라도 정렬 개념이 없습니다.
Ricardo Cárdenes

21
Python 3.7 이상 :sorted_dict = dict(sorted(unsorted_dict.items()))
aksh1618

10
python 3.7 이상은 기본적으로 주문되기 때문에 orderedDict가 필요하지 않습니다 :-)
Aneuway

3
python 3.7.4 매뉴얼에서 : "사전에서 list (d)를 수행하면 사전에 사용 된 모든 키 목록이 삽입 순서대로 반환됩니다." 따라서 게재 신청서는 보존되어 있으며 신뢰할 수 있습니다.
Mostafa Hadian

415

사전 자체에는 주문한 항목이 없습니다. 어떤 순서로 인쇄하려는 경우 다음과 같은 예가 있습니다.

Python 2.4 이상에서 :

mydict = {'carl':40,
          'alan':2,
          'bob':1,
          'danny':3}

for key in sorted(mydict):
    print "%s: %s" % (key, mydict[key])

제공합니다 :

alan: 2
bob: 1
carl: 40
danny: 3

(2.4 이하의 파이썬 :)

keylist = mydict.keys()
keylist.sort()
for key in keylist:
    print "%s: %s" % (key, mydict[key])

출처 : http://www.saltycrane.com/blog/2007/09/how-to-sort-python-dictionary-by-keys/


2
NPE의 답변에서와 같이 Python 2.4 이상에서 OrderedDict를 사용할 수도 있습니다
radtek

1
그리고 items ()를 사용한다면 다음과 같이 할 수 있습니다for key, value in sorted(mydict.items())"
beep_check

사전 자체에는 주문한 항목이 없습니다 -> 더 이상 사실이 아닙니다!
minexew

어떻게 설명 할 수 있습니까?
제임스

204

에서 파이썬 collections라이브러리 문서 :

>>> from collections import OrderedDict

>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

>>> # dictionary sorted by key -- OrderedDict(sorted(d.items()) also works
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])

4
대박! 당신이 순서 (내림차순 오름차순) 되돌리고 싶은 경우 얘들 아 당신은 단순히 추가 reverse=TrueOrderedDict(sorted(d.items(), reverse=True, key=lambda t: t[0]))
benscabbia

1
PyCharm에서 어떤 사전을 사용하든 항상 다음과 같은 경고가 표시됩니다.Unexpected type(s): (List[str]) Possible types: (Mapping) (Iterable[Tuple[Any, Any]])
Euler_Salter

153

CPython / PyPy 3.6 및 Python 3.7 이상의 경우 다음을 사용하여 쉽게 수행 할 수 있습니다.

>>> d = {2:3, 1:89, 4:5, 3:0}
>>> dict(sorted(d.items()))
{1: 89, 2: 3, 3: 0, 4: 5}

3
같은 것을 쓰는 또 다른 방법은 이해력을 사용하는 것입니다 : {key:d[key] for key in sorted(d.keys())}
flow2k

41

키를 정렬 된 순서로 자동 유지 관리하는 사전 구현을 제공하는 많은 Python 모듈이 있습니다. 순수 Python 및 빠른 C 구현 인 sortedcontainers 모듈을 고려하십시오 . 서로 벤치 마크 된 다른 인기있는 옵션과 의 성능 비교 도 있습니다.

반복하면서 키 / 값 쌍을 지속적으로 추가하고 제거해야하는 경우 순서가 지정된 dict를 사용하는 것은 부적절한 솔루션입니다.

>>> from sortedcontainers import SortedDict
>>> d = {2:3, 1:89, 4:5, 3:0}
>>> s = SortedDict(d)
>>> s.items()
[(1, 89), (2, 3), (3, 0), (4, 5)]

SortedDict 유형은 내장 dict 유형으로는 불가능한 색인 된 위치 검색 및 삭제도 지원합니다.

>>> s.iloc[-1]
4
>>> del s.iloc[2]
>>> s.keys()
SortedSet([1, 2, 4])

32

간단히:

d = {2:3, 1:89, 4:5, 3:0}
sd = sorted(d.items())

for k,v in sd:
    print k, v

산출:

1 89
2 3
3 0
4 5

6
sd사전이 아닌 튜플 목록입니다. (여전히 유용합니다.)
nischi

24

다른 사람들이 언급했듯이 사전은 본질적으로 순서가 없습니다. 그러나 문제가 순서대로 사전을 표시하는__str__ 경우 사전 서브 클래스 의 메소드를 대체 하고 내장 클래스 대신이 사전 클래스를 사용할 수 있습니다 dict. 예 :

class SortedDisplayDict(dict):
   def __str__(self):
       return "{" + ", ".join("%r: %r" % (key, self[key]) for key in sorted(self)) + "}"


>>> d = SortedDisplayDict({2:3, 1:89, 4:5, 3:0})
>>> d
{1: 89, 2: 3, 3: 0, 4: 5}

이것은 키가 저장되는 방식, 키를 반복 할 때 키가 반환되는 순서 print, 파이썬 콘솔에서 또는 파이썬 콘솔에서 표시되는 방식에 대해서는 아무것도 변경하지 않습니다 .


19

다른 방법을 찾았습니다.

import json
print json.dumps(d, sort_keys = True)

upd :
1. 이것은 또한 @DanielF 덕분에 중첩 된 객체를 정렬합니다.
2. 파이썬 사전은 순서가 정해지지 않기 때문에 인쇄에 적합하거나 str에만 할당 할 수 있습니다.


그러나 이것은 또한 원치 않는 중첩 객체의 키를 정렬합니다.
Daniel F

이것은 목록이 아닌 사전 만 정렬합니다. 예를 들어 dict.keys ()는 목록이므로 정렬되지 않습니다.
앤드류


13

파이썬 3.6은 파이썬 3.6 이전에 정렬되지 않았습니다. Python 3.6의 CPython 구현에서 사전은 삽입 순서를 유지합니다. Python 3.7부터는 언어 기능이됩니다.

Python 3.6의 변경 로그에서 ( https://docs.python.org/3.6/whatsnew/3.6.html#whatsnew36-compactdict ) :

이 새로운 구현의 순서 유지 측면은 구현 세부 사항으로 간주되며 의존해서는 안됩니다 (향후 변경 될 수 있지만 언어 사양을 변경하기 전에 몇 가지 릴리스에 대해 언어 로이 새로운 dict 구현을 갖는 것이 바람직합니다 현재와 ​​미래의 모든 파이썬 구현에 대한 순서 유지 의미론을 강제하기 위해; 이것은 또한 임의의 반복 순서가 여전히 유효한 이전 버전의 언어 (예 : Python 3.5)와 역 호환성을 유지하는 데 도움이됩니다.

Python 3.7 문서 ( https://docs.python.org/3.7/tutorial/datastructures.html#dictionaries )에서 :

사전에서 list (d)를 수행하면 사전에 사용 된 모든 키 목록이 삽입 순서대로 반환됩니다 (정렬하려면 sorted (d)를 대신 사용하십시오).

따라서 이전 버전과 달리 Python 3.6 / 3.7 이후의 dict을 정렬 할 수 있습니다. 하위 사전을 포함하여 중첩 된 사전을 정렬하려면 다음을 수행하십시오.

test_dict = {'a': 1, 'c': 3, 'b': {'b2': 2, 'b1': 1}}

def dict_reorder(item):
    return {k: sort_dict(v) if isinstance(v, dict) else v for k, v in sorted(item.items())}

reordered_dict = dict_reorder(test_dict)

https://gist.github.com/ligyxy/f60f0374defc383aa098d44cfbd318eb


11

여기에서 키를 사용하여 파이썬 dict를 정렬하는 가장 간단한 해결책을 찾았습니다 pprint. 예.

>>> x = {'a': 10, 'cd': 20, 'b': 30, 'az': 99} 
>>> print x
{'a': 10, 'b': 30, 'az': 99, 'cd': 20}

그러나 pprint를 사용하는 동안 정렬 된 dict를 반환합니다.

>>> import pprint 
>>> pprint.pprint(x)
{'a': 10, 'az': 99, 'b': 30, 'cd': 20}

10

사전을 정렬하는 쉬운 방법이 있습니다.

귀하의 질문에 따르면

해결책은 다음과 같습니다.

c={2:3, 1:89, 4:5, 3:0}
y=sorted(c.items())
print y

(여기서 c는 사전의 이름입니다.)

이 프로그램은 다음과 같은 출력을 제공합니다.

[(1, 89), (2, 3), (3, 0), (4, 5)]

당신이 원했던 것처럼.

다른 예는 다음과 같습니다.

d={"John":36,"Lucy":24,"Albert":32,"Peter":18,"Bill":41}
x=sorted(d.keys())
print x

출력을 제공합니다.['Albert', 'Bill', 'John', 'Lucy', 'Peter']

y=sorted(d.values())
print y

출력을 제공합니다.[18, 24, 32, 36, 41]

z=sorted(d.items())
print z

출력을 제공합니다.

[('Albert', 32), ('Bill', 41), ('John', 36), ('Lucy', 24), ('Peter', 18)]

따라서 키, 값 및 항목으로 변경하면 원하는대로 인쇄 할 수 있습니다.


8

원하는 것을 정확하게 생성합니다.

 D1 = {2:3, 1:89, 4:5, 3:0}

 sort_dic = {}

 for i in sorted(D1):
     sort_dic.update({i:D1[i]})
 print sort_dic


{1: 89, 2: 3, 3: 0, 4: 5}

그러나 이것은 내가 최근에 배운 다른 사전과는 다른 행동을 보일 수 있기 때문에 이것을하는 올바른 방법은 아닙니다. 따라서 여기에서 공유하고있는 쿼리에 대한 응답으로 Tim이 완벽한 방법을 제안했습니다.

from collections import OrderedDict
sorted_dict = OrderedDict(sorted(D1.items(), key=lambda t: t[0]))

"사전마다 다른 행동을 보여줍니다"는 무엇을 의미합니까? 정렬 된 "명백한 동작"은 무엇입니까?
ingyhere 2011

6

가장 쉬운 방법은 dict를 키별로 정렬하고 정렬 된 키 : 값 쌍을 새 dict에 저장하는 것입니다.

dict1 = {'renault': 3, 'ford':4, 'volvo': 1, 'toyota': 2} 
dict2 = {}                  # create an empty dict to store the sorted values
for key in sorted(dict1.keys()):
    if not key in dict2:    # Depending on the goal, this line may not be neccessary
        dict2[key] = dict1[key]

더 명확하게하려면 :

dict1 = {'renault': 3, 'ford':4, 'volvo': 1, 'toyota': 2} 
dict2 = {}                  # create an empty dict to store the sorted     values
for key in sorted(dict1.keys()):
    if not key in dict2:    # Depending on the goal, this line may not be  neccessary
        value = dict1[key]
        dict2[key] = value

6

질문에 따라 현재 사전을 키별로 정렬하여 새 사전을 작성할 수 있습니다.

이것은 당신의 사전입니다

d = {2:3, 1:89, 4:5, 3:0}

람다 함수를 사용하여이 d를 정렬하여 새 사전 d1을 만듭니다.

d1 = dict(sorted(d.items(), key = lambda x:x[0]))

d1은 d의 키를 기준으로 정렬 된 {1 : 89, 2 : 3, 3 : 0, 4 : 5} 여야합니다.


5

파이썬 dicts는 순서가 없습니다. 가장 일반적인 사용 사례는 조회를 수행하는 것이므로 일반적으로 문제가되지 않습니다.

원하는 것을 수행하는 가장 간단한 방법 collections.OrderedDict은 정렬 된 순서대로 요소를 삽입하는 것입니다.

ordered_dict = collections.OrderedDict([(k, d[k]) for k in sorted(d.keys())])

위의 다른 사람들이 제안했듯이 반복 해야하는 경우 가장 간단한 방법은 정렬 된 키를 반복하는 것입니다. 예-

키별로 정렬 된 값을 인쇄하십시오.

# create the dict
d = {k1:v1, k2:v2,...}
# iterate by keys in sorted order
for k in sorted(d.keys()):
    value = d[k]
    # do something with k, value like print
    print k, value

키별로 정렬 된 값 목록을 가져옵니다.

values = [d[k] for k in sorted(d.keys())]

2
for k,value in sorted(d.items()):더 나은 : 루프에서 다시 키로 dict에 액세스하지 마십시오
Jean-François Fabre

4

한 줄 dict 정렬을 생각해 냈습니다.

>> a = {2:3, 1:89, 4:5, 3:0}
>> c = {i:a[i] for i in sorted(a.keys())}
>> print(c)
{1: 89, 2: 3, 3: 0, 4: 5}
[Finished in 0.4s]

이것이 도움이 되길 바랍니다.


4

이 함수는 키를 기준으로 모든 사전을 재귀 적 으로 정렬합니다 . 즉, 사전에있는 값도 사전 인 경우 키로도 정렬됩니다. CPython 3.6 이상에서 실행중인 경우 간단한 사용 dict대신 간단한 변경을 수행 OrderedDict할 수 있습니다.

from collections import OrderedDict

def sort_dict(d):
    items = [[k, v] for k, v in sorted(d.items(), key=lambda x: x[0])]
    for item in items:
        if isinstance(item[1], dict):
            item[1] = sort_dict(item[1])
    return OrderedDict(items)
    #return dict(items)

2

여러분이 일을 복잡하게 만들고 있습니다 ... 정말 간단합니다

from pprint import pprint
Dict={'B':1,'A':2,'C':3}
pprint(Dict)

출력은 다음과 같습니다.

{'A':2,'B':1,'C':3}

pprint 정렬 사전을 알지 못했기 때문에 찬성했습니다.하지만 OP는 정렬되지 않은 정렬에서 정렬 된 dict로 "가는"것에 대해 실제로 물었습니다.
Captain Lepton

이 방법은 pprint가 none을 반환하므로 체인 할당을 허용하지 않습니다. >>> adict = { 'B': 1, 'A': 2, 'C': 3} >>> ppdict = pprint (adict) { 'A': 2, 'B': 1, 'C': 3} >>> ppdict.type () 역 추적 (가장 최근 호출) : <모듈>의 1 행 "<stdin>"파일 AttributeError : 'NoneType'객체에 'type'속성이 없습니다.

2

가장 간단한 해결책은 dict 키 목록이 정렬 된 순서로 가져온 다음 dict를 반복해야한다는 것입니다. 예를 들어

a1 = {'a':1, 'b':13, 'd':4, 'c':2, 'e':30}
a1_sorted_keys = sorted(a1, key=a1.get, reverse=True)
for r in a1_sorted_keys:
    print r, a1[r]

출력은 다음과 같습니다

e 30
b 13
d 4
c 2
a 1

2

이것을하는 쉬운 방법 :

d = {2:3, 1:89, 4:5, 3:0}

s = {k : d[k] for k in sorted(d)}

s
Out[1]: {1: 89, 2: 3, 3: 0, 4: 5} 

1

2.7에서 두 방법의 타이밍 비교는 사실상 동일하다는 것을 보여줍니다.

>>> setup_string = "a = sorted(dict({2:3, 1:89, 4:5, 3:0}).items())"
>>> timeit.timeit(stmt="[(k, val) for k, val in a]", setup=setup_string, number=10000)
0.003599141953657181

>>> setup_string = "from collections import OrderedDict\n"
>>> setup_string += "a = OrderedDict({1:89, 2:3, 3:0, 4:5})\n"
>>> setup_string += "b = a.items()"
>>> timeit.timeit(stmt="[(k, val) for k, val in b]", setup=setup_string, number=10000)
0.003581275490432745 

1
from operator import itemgetter
# if you would like to play with multiple dictionaries then here you go:
# Three dictionaries that are composed of first name and last name.
user = [
    {'fname': 'Mo', 'lname': 'Mahjoub'},
    {'fname': 'Abdo', 'lname': 'Al-hebashi'},
    {'fname': 'Ali', 'lname': 'Muhammad'}
]
#  This loop will sort by the first and the last names.
# notice that in a dictionary order doesn't matter. So it could put the first name first or the last name first. 
for k in sorted (user, key=itemgetter ('fname', 'lname')):
    print (k)

# This one will sort by the first name only.
for x in sorted (user, key=itemgetter ('fname')):
    print (x)

1
dictionary = {1:[2],2:[],5:[4,5],4:[5],3:[1]}

temp=sorted(dictionary)
sorted_dict = dict([(k,dictionary[k]) for i,k in enumerate(temp)])

sorted_dict:
         {1: [2], 2: [], 3: [1], 4: [5], 5: [4, 5]}


0

내 제안은 항목을 추가 할 때 dict를 정렬하거나 dict을 정렬하여 유지하고 앞으로 항목을 추가해야 할 수 있기 때문에 이것입니다.

진행하면서 dict처음부터 다시 시작 하십시오 . 키 목록이있는 두 번째 데이터 구조 인 목록이 있습니다. bisect 패키지에는 정렬 목록에 삽입하거나 dict를 완전히 채운 후 목록을 정렬 할 수있는 정렬 기능이 있습니다. 이제 dict을 반복 할 때 dict 구조 (정렬 용이 아님)의 표시에 대해 걱정하지 않고 목록을 반복하여 순서대로 각 키에 액세스합니다.


-1
l = dict.keys()
l2 = l
l2.append(0)
l3 = []
for repeater in range(0, len(l)):
    smallnum = float("inf")
    for listitem in l2:
        if listitem < smallnum:
            smallnum = listitem
    l2.remove(smallnum)
    l3.append(smallnum)
l3.remove(0)
l = l3

for listitem in l:
    print(listitem)

3
14 개의 다른 답변이 있습니다. 코드를 조금 설명하고 왜 다른 솔루션보다 더 좋을 수 있습니까?
FelixSFD

Downvoted-의미없는 변수 이름이 l, l2, l3 인 읽을 수없는 코드입니다. 파이썬 표준 함수에 대한 지식이없는 간접적이고 비효율적 인 알고리즘을 시도하는 것으로 보이며 어떤 경우에도 원래 게시물의 작은 예제에서 테스트 할 때 작동하지 않습니다.
Captain Lepton
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.