Python 切片字典

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29216889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 04:13:09  来源:igfitidea点击:

Slicing a dictionary

pythondictionary

提问by Zak

I have a dictionary, and would like to pass a part of it to a function, that part being given by a list (or tuple) of keys. Like so:

我有一本字典,想将它的一部分传递给一个函数,该部分由键列表(或元组)给出。像这样:

# the dictionary
d = {1:2, 3:4, 5:6, 7:8}

# the subset of keys I'm interested in
l = (1,5)

Now, ideally I'd like to be able to do this:

现在,理想情况下,我希望能够做到这一点:

>>> d[l]
{1:2, 5:6}

... but that's not working, since it will look for a key named (1,5). And d[1,5]isn't even valid Python (though it seems it would be handy).

...但这不起作用,因为它会寻找一个名为(1,5). 而且d[1,5]甚至不是有效的Python(尽管现在看来,这将方便)。

I know I can do this:

我知道我可以这样做:

>>> dict([(key, value) for key,value in d.iteritems() if key in l])
{1: 2, 5: 6}

or this:

或这个:

>>> dict([(key, d[key]) for key in l])

which is more compact ... but I feel there must be a "better" way of doing this. Am I missing a more elegant solution?

这更紧凑......但我觉得必须有一种“更好”的方式来做到这一点。我错过了更优雅的解决方案吗?

(I'm using Python 2.7)

(我使用的是 Python 2.7)

采纳答案by Padraic Cunningham

You should be iterating over the tuple and checking if the key is in the dict not the other way around, if you don't check if the key exists and it is not in the dict you are going to get a key error:

您应该迭代元组并检查键是否在 dict 中而不是相反,如果您不检查键是否存在并且它不在 dict 中,您将收到一个键错误:

print({k:d[k] for k in l if k in d})

Some timings:

一些时间:

 {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

I don't see how {k:d[k] for k in l}is not readable or elegant and if all elements are in d then it is pretty efficient.

我不明白如何{k:d[k] for k in l}不可读或不优雅,如果所有元素都在 d 中,那么它非常有效。

回答by Martijn Pieters

Use a set to intersect on the dict.viewkeys()dictionary view:

使用集合在dict.viewkeys()字典视图上相交:

l = {1, 5}
{key: d[key] for key in d.viewkeys() & l}

This is Python 2 syntax, in Python 3 use d.keys().

这是 Python 2 语法,在 Python 3 中使用d.keys().

This still uses a loop, but at least the dictionary comprehension is a lot more readable. Using set intersections is very efficient, even if dor lis large.

这仍然使用循环,但至少字典理解更具可读性。使用集合交集非常有效,即使dl很大。

Demo:

演示:

>>> 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}

回答by kindall

Write a dictsubclass that accepts a list of keys as an "item" and returns a "slice" of the dictionary:

编写一个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)

Usage:

用法:

d = SliceableDict({1:2, 3:4, 5:6, 7:8})
d[[1, 5]]   # {1: 2, 5: 6}

Or if you want to use a separate method for this type of access, you can use *to accept any number of arguments:

或者,如果您想对这种类型的访问使用单独的方法,您可以使用*来接受任意数量的参数:

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

回答by itzMEonTV

set intersectionand dict comprehensioncan be used here

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}

回答by Cesar Canassa

On Python 3 you can use the itertools isliceto slice the dict.items()iterator

在 Python 3 上,您可以使用 itertoolsislicedict.items()迭代器进行切片

import itertools

d = {1: 2, 3: 4, 5: 6}

dict(itertools.islice(d.items(), 2))

{1: 2, 3: 4}

Note:this solution does nottake into account specific keys. It slices by internal ordering of d, which in Python 3.7+ is guaranteed to be insertion-ordered.

注意:此解决方案并没有考虑到特定按键。它按 的内部顺序切片d,在 Python 3.7+ 中保证是插入顺序的。

回答by diman Bond

the dictionary

词典

d = {1:2, 3:4, 5:6, 7:8}

the subset of keys I'm interested in

我感兴趣的键子集

l = (1,5)

answer

回答

{key: d[key] for key in l}