Python-dict에서 처음 N 개의 키 : 값 쌍 반환


108

다음 사전을 고려하십시오. d :

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

d (이 경우 N <= 4)에서 처음 N 개의 키 : 값 쌍을 반환하고 싶습니다. 이를 수행하는 가장 효율적인 방법은 무엇입니까?


1
주의. 답변에 많은 잘못된 정보가있는 것 같습니다. 내 테스트에 따르면 단일 솔루션이 list(d.items())[:4]. list ()는 많은 답변에 대한 기본 구현입니다.
BSalita

답변:


114

a dict는 어떤 키가 먼저 삽입되었는지 기억하지 못 하기 때문에 "처음 n"키 같은 것은 없습니다.

당신이 얻을 수 있는 n 개의 키 - 값 쌍 생각을 :

n_items = take(n, d.iteritems())

이것은의 구현 사용 take로부터 itertools조리법 :

from itertools import islice

def take(n, iterable):
    "Return first n items of the iterable as a list"
    return list(islice(iterable, n))

온라인 작업보기 : ideone


Python 3.6 용 업데이트

n_items = take(n, d.items())

42
나는 파이썬 3의 사람들을 위해 iteritems대체되어야 한다고 믿습니다items
Monica Heddneck

1
@MonicaHeddneck, 훌륭합니다.이 댓글을 추가해 주셔서 감사합니다.
칼 베이커

12
초보자- take()어디에서나 파이썬 코드베이스의 일부입니까? 아니면 여기에 대한 답변에서 정의한 기능입니까? 코드베이스의 일부인 것처럼 물어 보면 찾거나 가져올 수 없습니다. :)
Scott Borden

81

무엇이든 검색하는 매우 효율적인 방법은 목록 또는 사전 이해를 슬라이싱과 결합하는 것입니다. 항목을 주문할 필요가없는 경우 (n 개의 임의 쌍만 원함) 다음과 같은 사전 이해를 사용할 수 있습니다.

# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}

일반적으로 이와 같은 이해는 "for x in y"루프보다 항상 실행 속도가 더 빠릅니다. 또한 .keys ()를 사용하여 사전 키 목록을 만들고 해당 목록을 분할하면 새 사전을 빌드 할 때 불필요한 키를 '건드리지'않도록 할 수 있습니다.

키 (값만)가 필요하지 않은 경우 목록 이해를 사용할 수 있습니다.

first2vals = [v for v in mydict.values()[:2]]

키를 기준으로 정렬 된 값이 필요한 경우에는 그다지 문제가되지 않습니다.

first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]

또는 키가 필요한 경우 :

first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}

2
사전으로 값 쌍되지 목록으로, : 당신이 N 많은 키를 선택하려는 경우 하나는 더 나은 솔루션입니다
fermat4214

1
@ fermat4214이 명령 중 하나를 실행할 때 전체 사전이 인쇄되면 문제가 있습니까?
생명의 테드 테일러

list (mydict) [: 2]는 사전을 정렬 할 필요가없고 처음 2 개의 요소 만 필요하다면 낭비입니다. 사전에 1mil kv 쌍이 있으면 어떻게됩니까? 모든 것을 목록으로 변환하는 것은 비용이 많이 듭니다. Mark Byers의 솔루션이 훨씬 낫습니다.
JJ

이것이 해결책이되어야합니다!
Guenter

14

파이썬의 dict는 순서가 지정되지 않았으므로 "처음 N"키를 요청하는 것은 의미가 없습니다.

collections.OrderedDict즉 당신이 필요하다면 클래스를 사용할 수 있습니다. 처음 네 가지 요소를 다음과 같이 효율적으로 얻을 수 있습니다.

import itertools
import collections

d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')))
x = itertools.islice(d.items(), 0, 4)

for key, value in x:
    print key, value

itertools.islice반복기에서 요소 조각을 느리게 가져올 수 있습니다. 결과를 재사용 할 수있게하려면 다음과 같이 목록이나 다른 것으로 변환해야합니다.

x = list(itertools.islice(d.items(), 0, 4))

게으른 표정이 아닙니다. `list (d.items ()) [: 4]보다 2 배 더 오래 걸립니다
BSalita

12
foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
iterator = iter(foo.items())
for i in range(3):
    print(next(iterator))

기본적으로 뷰 (dict_items)를 반복자로 전환 한 다음 next ()로 반복합니다.


2
환상적인 대답, 이것은이 페이지에서 나를 위해 일하고 읽을 수있는 유일한 대답입니다. 또한 이것이 Python 3에서 작동하는지 확인할 수 있는데, 이전 답변 중 일부는 그렇지 않은 것 같습니다.
cdahms

7

여기서 보지 못했어요. 정렬되지는 않지만 사전에서 일부 요소를 가져와야하는 경우 가장 간단한 구문입니다.

n = 2
{key:value for key,value in d.items()[0:n]}

7
코드를 시도했지만이 오류가 발생합니다. TypeError: 'dict_items' object is not subscriptable {key:value for key,value in stocks.items()[0:n]} (stocks는 내 사전의 이름입니다)
Moondra

2
@Moondra-사전 항목을 실행하기 전에 목록으로 변환해야합니다. 위의 코드 줄은 경우 {: 목록에서 키 값 (d.items ())에 대한 값 [n은 0] 키} 작동
인 Rajesh Mappu

{A : N for (A, N) in [x for x in d.items ()] [: 4]}
farid khafizov

6

파이썬 사전에서 상위 N 개 요소를 얻으려면 다음 코드 줄을 사용할 수 있습니다.

list(dictionaryName.items())[:N]

귀하의 경우 다음과 같이 변경할 수 있습니다.

list(d.items())[:4]

3

PEP 0265 참조사전 정렬에 를 . 그런 다음 앞서 언급 한 반복 가능한 코드를 사용합니다.

정렬 된 키-값 쌍에서 더 많은 효율성이 필요한 경우. 다른 데이터 구조를 사용하십시오. 즉, 정렬 된 순서와 키-값 연결을 유지하는 것입니다.

import bisect

kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)]
bisect.insort_left(kvlist, ('d', 4))

print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

3

py3에서 이것은 트릭을 할 것입니다.

{A:N for (A,N) in [x for x in d.items()][:4]}

{ 'a': 3, 'b': 2, 'c': 3, 'd': 4}


2

zip을 사용하여 답변을 추가하면됩니다.

{k: d[k] for k, _ in zip(d, range(n))}

1

이것은 귀하의 경우에 '가장 효율적인'것이 무엇인지에 달려 있습니다.

거대한 사전의 반 무작위 샘플을 원하는 경우 필요한만큼 많은 값을 foo사용 foo.iteritems()하고 가져 오면 명시적인 키 또는 항목 목록 생성을 피하는 게으른 작업입니다.

먼저 키를 정렬해야하는 경우 keys = foo.keys(); keys.sort()또는 같은 것을 사용하는 방법이 없습니다 sorted(foo.iterkeys()). 명시적인 키 목록을 작성해야합니다. 그런 다음 첫 번째 N을 슬라이스하거나 반복합니다 keys.

BTW 왜 '효율적인'방식에 관심이 있습니까? 프로그램을 프로파일 링했습니까? 그렇지 않은 경우 명확 하고 이해하기 쉬운 방법 . 병목 현상이 발생하지 않고 꽤 잘 할 가능성이 있습니다.


이것은 금융 프로그램에 대한 응용 프로그램이었고 가능한 한 효율적으로 모든 코드 줄을 작성하려고합니다. 나는 프로그램을 프로파일 링하지 않았으며 이것이 병목 현상이 아닐 것이라는 데 동의하지만 기본적으로 효율적인 솔루션을 요청하고 싶습니다. 답장을 보내 주셔서 감사합니다.
Jason Strimpel 2011

0

여러 가지 방법으로 접근 할 수 있습니다. 주문이 중요한 경우 다음을 수행 할 수 있습니다.

for key in sorted(d.keys()):
  item = d.pop(key)

주문이 문제가되지 않는 경우 다음을 수행 할 수 있습니다.

for i in range(4):
  item = d.popitem()

첫 조각에서 당신은 아마 그것을 호출해야 value보다는 item명확합니다.
agf

0

사전은 순서를 유지하지 않으므로 상위 N 개의 키 값 쌍을 선택하기 전에 정렬 할 수 있습니다.

import operator
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
#itemgetter(0)=sort by keys, itemgetter(1)=sort by values

이제 다음과 같은 메소드 구조를 사용하여 상위 'N'요소 검색을 수행 할 수 있습니다.

def return_top(elements,dictionary_element):
    '''Takes the dictionary and the 'N' elements needed in return
    '''
    topers={}
    for h,i in enumerate(dictionary_element):
        if h<elements:
            topers.update({i:dictionary_element[i]})
    return topers

상위 2 개 요소를 얻으려면 다음 구조를 사용하십시오.

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
d=return_top(2,d)
print(d)

0

Python 3 이상의 경우 처음 n 개 쌍을 선택하려면

n=4
firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}

0

사전을 고려하다

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

from itertools import islice
n = 3
list(islice(d.items(),n))

islice가 트릭을 할 것입니다 :) 도움이되기를 바랍니다!


0

이것은 매우 우아하지는 않지만 나를 위해 작동합니다.

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

x= 0
for key, val in d.items():
    if x == 2:
        break
    else:
        x += 1
        # Do something with the first two key-value pairs

0

위의 답변 중 몇 가지를 시도했으며 일부는 버전에 따라 다르며 버전 3.7에서 작동하지 않습니다.

또한 3.6 이후 모든 사전은 항목이 삽입되는 순서에 따라 정렬됩니다.

3.6 이후로 사전이 정렬 되었음에도 불구하고 정렬 된 구조로 작업 할 것으로 예상되는 일부 명령문이 작동하지 않는 것 같습니다.

저에게 가장 잘 맞는 OP 질문에 대한 답변입니다.

itr = iter(dic.items())
lst = [next(itr) for i in range(3)]

참고로, 5 배 더 느림lst = list(d.items())[:N]
BSalita
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.