我有一个字典,并希望将其中一部分传递给一个函数,该部分由一个列表(或元组)给出。像这样:
# the dictionary
d = {1:2, 3:4, 5:6, 7:8}
# the subset of keys I'm interested in
l = (1,5)
现在,理想情况下,我希望能够做到这一点:
>>> d[l]
{1:2, 5:6}
...但这不起作用,因为它会查找名为(1,5)
的密钥。
并且d[1,5]
甚至不是有效的Python(虽然它看起来很方便)。
我知道我可以这样做:
>>> dict([(key, value) for key,value in d.iteritems() if key in l])
{1: 2, 5: 6}
或者这个:
>>> dict([(key, d[key]) for key in l])
更紧凑 ......但我觉得必须有一个更好的"这样做的方式。我错过了一个更优雅的解决方案吗?
(我使用的是Python 2.7)
答案 0 :(得分:25)
你应该迭代元组并检查密钥是否在dict中,而不是相反,如果你不检查密钥是否存在而且它不在dict中你将得到一个密钥错误:
print({k:d[k] for k in l if k in d})
一些时间:
{k:d[k] for k in set(d).intersection(l)}
In [22]: %%timeit
l = xrange(100000)
{k:d[k] for k in l}
....:
100 loops, best of 3: 11.5 ms per loop
In [23]: %%timeit
l = xrange(100000)
{k:d[k] for k in set(d).intersection(l)}
....:
10 loops, best of 3: 20.4 ms per loop
In [24]: %%timeit
l = xrange(100000)
l = set(l)
{key: d[key] for key in d.viewkeys() & l}
....:
10 loops, best of 3: 24.7 ms per
In [25]: %%timeit
l = xrange(100000)
{k:d[k] for k in l if k in d}
....:
100 loops, best of 3: 17.9 ms per loop
我不知道{k:d[k] for k in l}
如何不可读或优雅,如果所有元素都在d中,那么效率非常高。
答案 1 :(得分:17)
使用一个集合在dict.viewkeys()
dictionary view:
l = {1, 5}
{key: d[key] for key in d.viewkeys() & l}
这是Python 2语法,在Python 3中使用d.keys()
。
这仍然使用循环,但至少字典理解更具可读性。即使d
或l
很大,使用集合交叉也非常有效。
演示:
>>> d = {1:2, 3:4, 5:6, 7:8}
>>> l = {1, 5}
>>> {key: d[key] for key in d.viewkeys() & l}
{1: 2, 5: 6}
答案 2 :(得分:15)
在Python 3上,你可以使用itertools islice
来切片dict.items()
迭代器
import itertools
d = {1: 2, 3: 4, 5: 6}
dict(itertools.islice(d.items(), 2))
{1: 2, 3: 4}
注意:此解决方案不会考虑特定密钥。它按d
的内部排序进行切片,在Python 3.7+中保证按插入顺序排列。
答案 3 :(得分:7)
编写一个dict
子类,接受一个键列表作为"项目"并返回"切片"字典:
class SliceableDict(dict):
default = None
def __getitem__(self, key):
if isinstance(key, list): # use one return statement below
# uses default value if a key does not exist
return {k: self.get(k, self.default) for k in key}
# raises KeyError if a key does not exist
return {k: self[k] for k in key}
# omits key if it does not exist
return {k: self[k] for k in key if k in self}
return dict.get(self, key)
用法:
d = SliceableDict({1:2, 3:4, 5:6, 7:8})
d[[1, 5]] # {1: 2, 5: 6}
或者,如果您想为此类访问使用单独的方法,可以使用*
接受任意数量的参数:
class SliceableDict(dict):
def slice(self, *keys):
return {k: self[k] for k in keys}
# or one of the others from the first example
d = SliceableDict({1:2, 3:4, 5:6, 7:8})
d.slice(1, 5) # {1: 2, 5: 6}
keys = 1, 5
d.slice(*keys) # same
答案 4 :(得分:7)
要对字典进行切片,请使用 d.items()
将其转换为元组列表,对列表进行切片并从中创建字典。
这里。
d = {1:2, 3:4, 5:6, 7:8}
获取前两个项目
first_two = dict(list(d.items())[:2])
first_two
{1: 2, 3: 4}
答案 5 :(得分:3)
d = {1:2, 3:4, 5:6, 7:8}
l = (1,5)
{key: d[key] for key in l}
答案 6 :(得分:2)
set intersection
和dict comprehension
可以在这里使用
# the dictionary
d = {1:2, 3:4, 5:6, 7:8}
# the subset of keys I'm interested in
l = (1,5)
>>>{key:d[key] for key in set(l) & set(d)}
{1: 2, 5: 6}