파이썬 사전 : 키 목록에 대한 값 목록 가져 오기


182

사전에 키 목록을 사용하여 해당 항목의 목록을 얻는 기본 제공 / 빠른 방법이 있습니까?

예를 들어

>>> mydict = {'one': 1, 'two': 2, 'three': 3}
>>> mykeys = ['three', 'one']

mykeys사전에서 해당 값을 목록으로 가져 오려면 어떻게 해야합니까?

>>> mydict.WHAT_GOES_HERE(mykeys)
[3, 1]

답변:


206

목록 이해는 이것을 수행하는 좋은 방법 인 것 같습니다.

>>> [mydict[x] for x in mykeys]
[3, 1]

1
경우 mydict함수 호출 (리턴한다 딕셔너리가 있음) 다음이, 오른쪽 함수를 여러 번 호출입니까?
endolith

1
@endolith 그렇습니다
Eric Romrell

108

list-comp 이외의 다른 두 가지 방법 :

  • 키를 찾을 수 없으면 빌드 목록 및 예외 발생 : map(mydict.__getitem__, mykeys)
  • Noneif 키가없는 빌드 목록 :map(mydict.get, mykeys)

또는를 사용 operator.itemgetter하면 튜플을 반환 할 수 있습니다.

from operator import itemgetter
myvalues = itemgetter(*mykeys)(mydict)
# use `list(...)` if list is required

참고 : Python3에서는 map목록이 아닌 반복자를 반환합니다. list(map(...))목록에 사용하십시오 .


54

약간의 속도 비교 :

Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Dec  7 2015, 14:10:42) [MSC v.1500 64 bit (AMD64)] on win32
In[1]: l = [0,1,2,3,2,3,1,2,0]
In[2]: m = {0:10, 1:11, 2:12, 3:13}
In[3]: %timeit [m[_] for _ in l]  # list comprehension
1000000 loops, best of 3: 762 ns per loop
In[4]: %timeit map(lambda _: m[_], l)  # using 'map'
1000000 loops, best of 3: 1.66 µs per loop
In[5]: %timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
1000000 loops, best of 3: 1.65 µs per loop
In[6]: %timeit map(m.__getitem__, l)
The slowest run took 4.01 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 853 ns per loop
In[7]: %timeit map(m.get, l)
1000000 loops, best of 3: 908 ns per loop
In[33]: from operator import itemgetter
In[34]: %timeit list(itemgetter(*l)(m))
The slowest run took 9.26 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 739 ns per loop

따라서 목록 이해와 itemgetter가 가장 빠른 방법입니다.

업데이트 : 큰 무작위 목록과지도의 경우 약간 다른 결과가있었습니다.

Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Dec  7 2015, 14:10:42) [MSC v.1500 64 bit (AMD64)] on win32
In[2]: import numpy.random as nprnd
l = nprnd.randint(1000, size=10000)
m = dict([(_, nprnd.rand()) for _ in range(1000)])
from operator import itemgetter
import operator
f = operator.itemgetter(*l)
%timeit f(m)
%timeit list(itemgetter(*l)(m))
%timeit [m[_] for _ in l]  # list comprehension
%timeit map(m.__getitem__, l)
%timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
%timeit map(m.get, l)
%timeit map(lambda _: m[_], l)
1000 loops, best of 3: 1.14 ms per loop
1000 loops, best of 3: 1.68 ms per loop
100 loops, best of 3: 2 ms per loop
100 loops, best of 3: 2.05 ms per loop
100 loops, best of 3: 2.19 ms per loop
100 loops, best of 3: 2.53 ms per loop
100 loops, best of 3: 2.9 ms per loop

따라서이 경우 명확한 승자는 f = operator.itemgetter(*l); f(m)이고 외부인 은 분명 map(lambda _: m[_], l)합니다.

Python 3.6.4 업데이트 :

import numpy.random as nprnd
l = nprnd.randint(1000, size=10000)
m = dict([(_, nprnd.rand()) for _ in range(1000)])
from operator import itemgetter
import operator
f = operator.itemgetter(*l)
%timeit f(m)
%timeit list(itemgetter(*l)(m))
%timeit [m[_] for _ in l]  # list comprehension
%timeit list(map(m.__getitem__, l))
%timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
%timeit list(map(m.get, l))
%timeit list(map(lambda _: m[_], l)
1.66 ms ± 74.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.1 ms ± 93.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.58 ms ± 88.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.36 ms ± 60.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.98 ms ± 142 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.7 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3.14 ms ± 62.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

따라서 Python 3.6.4의 결과는 거의 동일합니다.


15

세 가지 방법이 있습니다.

모금 KeyError키가 발견되지 않는 경우 :

result = [mapping[k] for k in iterable]

누락 된 키의 기본값입니다.

result = [mapping.get(k, default_value) for k in iterable]

누락 된 키를 건너 뜁니다.

result = [mapping[k] for k in iterable if k in mapping]

found_keys = mapping.keys() & iterableTypeError: unsupported operand type(s) for &: 'list' and 'list'파이썬 2.7을 제공합니다 . `found_keys = [반복 가능한 키인 경우 mapping.keys ()의 키에 대한 키]가 가장 효과적입니다
NotGaeL

10

이 시도:

mydict = {'one': 1, 'two': 2, 'three': 3}
mykeys = ['three', 'one','ten']
newList=[mydict[k] for k in mykeys if k in mydict]
print newList
[3, 1]

7

이 시도:

mydict = {'one': 1, 'two': 2, 'three': 3}
mykeys = ['three', 'one'] # if there are many keys, use a set

[mydict[k] for k in mykeys]
=> [3, 1]

@PeterDeGlopper 혼란 스럽습니다. items()추가 조회를하지 않아도 len(mydict)*len(mykeys)됩니다. 여기 에는 작업 이 없습니다 ! (나는 세트를 사용하고 있음을 통지)
오스카르 로페스

@ ÓscarLópez 그렇습니다. 사전의 모든 요소를 ​​검사하고 있습니다. iteritems는 필요할 때까지 생성하지 않으므로 중개자 목록 구성을 피할 수 있지만 mydict의 모든 k에 대해 여전히 'k in mykeys'(순서 len (mykeys)이므로 목록입니다)를 실행합니다. mykeys를 실행하는 간단한 목록 이해와 비교할 때 완전히 불필요합니다.
피터 DeGlopper

@ inspectorG4dget @PeterDeGlopper 멤버쉽 작업 mykeys은 상시 상각됩니다. 목록이 아닌 세트를 사용하고 있습니다
Óscar López

2
OP의 목록을 집합으로 변환하면 적어도 선형으로 설정되지만 순서가 손실 될뿐 아니라 잘못된 데이터 구조에서는 여전히 선형입니다. 10k 사전의 경우와 mykeys의 2 개의 키를 고려하십시오. 솔루션은 간단한 목록 이해를위한 두 개의 사전 조회와 비교하여 10k 세트 멤버쉽 테스트를 수행합니다. 일반적으로 키 수는 사전 요소 수보다 적을 것이라고 가정하는 것이 안전합니다. 그렇지 않은 경우 접근 방식에서는 반복되는 요소를 생략합니다.
Peter DeGlopper


1

Pandas는 매우 우아하게 수행하지만 ofc 목록 이해는 항상 더 기술적으로 Pythonic 일 것입니다. 나는 지금 속도 비교를 할 시간이 없다 (나중에 돌아와서 넣을 것이다) :

import pandas as pd
mydict = {'one': 1, 'two': 2, 'three': 3}
mykeys = ['three', 'one']
temp_df = pd.DataFrame().append(mydict)
# You can export DataFrames to a number of formats, using a list here. 
temp_df[mykeys].values[0]
# Returns: array([ 3.,  1.])

# If you want a dict then use this instead:
# temp_df[mykeys].to_dict(orient='records')[0]
# Returns: {'one': 1.0, 'three': 3.0}

-1

또는 mydict.keys()사전에 대한 내장 메소드 호출입니다. 또한 탐색 mydict.values()하고mydict.items() .

// 아, OP 포스트는 나를 혼란스럽게했다.


5
내장 메소드는 유용하지만 주어진 키 목록에서 해당 항목의 목록을 제공하지 않습니다. 이 답변은이 특정 질문에 대한 정답이 아닙니다.
stenix

-1

파이썬 종료 후 : 주어진 순서로 dict 값에서 목록을 만드는 효율적인 방법

목록을 작성하지 않고 키 검색

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import collections


class DictListProxy(collections.Sequence):
    def __init__(self, klist, kdict, *args, **kwargs):
        super(DictListProxy, self).__init__(*args, **kwargs)
        self.klist = klist
        self.kdict = kdict

    def __len__(self):
        return len(self.klist)

    def __getitem__(self, key):
        return self.kdict[self.klist[key]]


myDict = {'age': 'value1', 'size': 'value2', 'weigth': 'value3'}
order_list = ['age', 'weigth', 'size']

dlp = DictListProxy(order_list, myDict)

print(','.join(dlp))
print()
print(dlp[1])

출력 :

value1,value3,value2

value3

목록에서 제공 한 순서와 일치하는


-2
reduce(lambda x,y: mydict.get(y) and x.append(mydict[y]) or x, mykeys,[])

dict에없는 키가있는 경우.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.