2013-08-26 101 views
102

Có cách tích hợp/nhanh chóng để sử dụng danh sách các phím vào từ điển để nhận danh sách các mục tương ứng không?Từ điển Python: Lấy danh sách các giá trị cho danh sách các phím

Ví dụ tôi có:

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

Làm thế nào tôi có thể sử dụng mykeys để có được giá trị tương ứng trong từ điển như một danh sách?

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

Trả lời

113

Một danh sách hiểu có vẻ là một cách tốt để làm điều này:

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

Hoặc chỉ cần mydict.keys() Đó là một lời gọi phương thức dựng sẵn cho từ điển. Đồng thời khám phá mydict.values()mydict.items().

// Ah, OP post nhầm lẫn tôi.

+3

Phương pháp được xây dựng hữu ích nhưng không cung cấp danh sách các mục tương ứng một danh sách các phím. Câu trả lời này không phải là câu trả lời đúng cho câu hỏi cụ thể này. – stenix

5

Hãy thử điều này:

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] 
+2

Tại sao bạn lại làm điều đó? Đó là thứ tự len (mydict) * len (mykeys) cho một cái gì đó có thể được thực hiện chỉ trong len (mykeys) tra cứu từ điển. –

+0

@PeterDeGlopper bạn đang bối rối. 'items()' được ưa thích, nó không phải thực hiện tra cứu bổ sung, không có hoạt động 'len (mydict) * len (mykeys)' ở đây! (thông báo rằng tôi đang sử dụng một tập hợp) –

+0

@PeterDeGlopper là đúng. Bạn đang lặp qua tất cả các cặp trong dict (O (len (mydict))) và kiểm tra xem mỗi khóa có trong 'mykeys' (O (len (mykeys)) mỗi lần). Tôi muốn giới thiệu '[mydict [k] cho k in mykeys]', điều này cũng giữ nguyên thứ tự của giá trị dựa trên các phím đơn đặt hàng trong 'mykeys' – inspectorG4dget

51

Một vài cách khác hơn là danh sách-comp:

  • danh sách xây dựng và ném ngoại lệ nếu không tìm thấy chìa khóa: map(mydict.__getitem__, mykeys)
  • danh sách Xây dựng với None nếu chủ chốt không tìm thấy: map(mydict.get, mykeys)

Ngoài ra, sử dụng operator.itemgetter có thể trả về một tuple:

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

Điều này có nhiều giải pháp tốt hơn so với IMO được chấp nhận. – spectras

-1

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

trong trường hợp có những phím không dict.

5

Dưới đây là ba cách.

Nâng KeyError khi phím không được tìm thấy:

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

Mặc định giá trị cho thiếu phím.

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

Bỏ qua các phím bị thiếu.

found_keys = mapping.keys() & iterable 
result = [mapping[k] for k in iterable if k in found_keys] 
21

Một chút tốc độ so sánh:

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 

Vì vậy, danh sách hiểu và itemgetter là những cách nhanh nhất để làm điều này.

UPDATE: Đối với danh sách ngẫu nhiên lớn và bản đồ tôi đã có một chút kết quả khác nhau:

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 

Vì vậy, trong trường hợp này người chiến thắng rõ ràng là f = operator.itemgetter(*l); f(m), và người ngoài rõ ràng: map(lambda _: m[_], l).

0

Tiếp theo đóng Python: efficient way to create a list from dict values with a given order

Lấy chìa khóa mà không cần xây dựng danh sách:

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]) 

Sản lượng:

value1,value3,value2 

value3 

nào phù hợp với trật tự cho bởi danh sách

10

Thử Điều này:

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] 
1

Pandas thực hiện điều này rất thanh lịch, mặc dù việc hiểu danh sách ofc sẽ luôn là kỹ thuật Pythonic hơn. Tôi không có thời gian để so sánh tốc độ ngay bây giờ (tôi sẽ quay lại sau và đưa nó vào):

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} 
Các vấn đề liên quan