从Python字典对象中提取键-值对子集?

时间:2022-06-02 07:38:45

I have a big dictionary object that has several key value pairs (about 16), but I am only interested in 3 of them. What is the best way (shortest/efficient/most elegant) to achieve that?

我有一个大的dictionary对象,它有几个键值对(大约16个),但我只对其中的3个感兴趣。达到这一目标的最佳方法(最短/有效/最优雅)是什么?

The best I know is:

我所知道的最好的是:

bigdict = {'a':1,'b':2,....,'z':26} 
subdict = {'l':bigdict['l'], 'm':bigdict['m'], 'n':bigdict['n']}

I am sure there is a more elegant way than this. Ideas?

我相信还有比这更优雅的方式。想法吗?

9 个解决方案

#1


272  

You could try:

你可以试试:

dict((k, bigdict[k]) for k in ('l', 'm', 'n'))

... or in Python 3 Python versions 2.7 or later (thanks to Fábio Diniz for pointing that out that it works in 2.7 too):

…或者在Python 3 Python版本2.7或更高版本中(感谢Fabio Diniz指出它在2.7中也适用):

{k: bigdict[k] for k in ('l', 'm', 'n')}

Update: As Håvard S points out, I'm assuming that you know the keys are going to be in the dictionary - see his answer if you aren't able to make that assumption. Alternatively, as timbo points out in the comments, if you want a key that's missing in bigdict to map to None, you can do:

更新:正如Havard S所指出的,我假设你知道这些键将会出现在字典中——如果你不能做出这样的假设,请查看他的答案。另外,正如timbo在评论中指出的,如果您想要将bigdict中的一个键映射为None,您可以这样做:

{k: bigdict.get(k, None) for k in ('l', 'm', 'n')}

If you're using Python 3, and you only want want keys in the new dict that actually exist in the original one, you can use the fact the view objects implement some set operations:

如果您使用的是Python 3,而您只想要在原来的版本中真正存在的新命令中需要的键,那么您可以使用视图对象实现一些集合操作的事实:

{k: bigdict[k] for k in bigdict.keys() & {'l', 'm', 'n'}}

#2


74  

A bit shorter, at least:

至少短一点:

wanted_keys = ['l', 'm', 'n'] # The keys you want
dict((k, bigdict[k]) for k in wanted_keys if k in bigdict)

#3


18  

interesting_keys = ('l', 'm', 'n')
subdict = {x: bigdict[x] for x in interesting_keys if x in bigdict}

#4


10  

This answer uses a dictionary comprehension similar to the selected answer, but will not except on a missing item.

这个答案使用一个类似于所选答案的字典理解,但不会除了一个缺失的项。

python 2 version:

python 2版本:

{k:v for k, v in bigDict.iteritems() if k in ('l', 'm', 'n')}

python 3 version:

python 3版:

{k:v for k, v in bigDict.items() if k in ('l', 'm', 'n')}

#5


8  

A bit of speed comparison for all mentioned methods:

所有上述方法的速度比较:

Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Jan 29 2016, 14:26:21) [MSC v.1500 64 bit (AMD64)] on win32
In[2]: import numpy.random as nprnd
keys = nprnd.randint(1000, size=10000)
bigdict = dict([(_, nprnd.rand()) for _ in range(1000)])

%timeit {key:bigdict[key] for key in keys}
%timeit dict((key, bigdict[key]) for key in keys)
%timeit dict(map(lambda k: (k, bigdict[k]), keys))
%timeit dict(filter(lambda i:i[0] in keys, bigdict.items()))
%timeit {key:value for key, value in bigdict.items() if key in keys}
100 loops, best of 3: 3.09 ms per loop
100 loops, best of 3: 3.72 ms per loop
100 loops, best of 3: 6.63 ms per loop
10 loops, best of 3: 20.3 ms per loop
100 loops, best of 3: 20.6 ms per loop

As it was expected: dictionary comprehensions are the best option.

正如预期的那样:字典理解是最好的选择。

#6


3  

Maybe:

可能:

subdict=dict([(x,bigdict[x]) for x in ['l', 'm', 'n']])

Python 3 even supports the following:

Python 3甚至支持以下内容:

subdict={a:bigdict[a] for a in ['l','m','n']}

Note that you can check for existence in dictionary as follows:

请注意,您可以在字典中检查是否存在如下:

subdict=dict([(x,bigdict[x]) for x in ['l', 'm', 'n'] if x in bigdict])

resp. for python 3

分别地。python 3

subdict={a:bigdict[a] for a in ['l','m','n'] if a in bigdict}

#7


3  

You can also use map (which is a very useful function to get to know anyway):

你也可以使用map(这是一个非常有用的函数来了解):

sd = dict(map(lambda k: (k, l.get(k, None)), l))

sd = dict(map(k: (k, l)得到(k,None)),l))

Example:

例子:

large_dictionary = {'a1':123, 'a2':45, 'a3':344} list_of_keys = ['a1', 'a3'] small_dictionary = dict(map(lambda key: (key, large_dictionary.get(key, None)), list_of_keys))

large_dictionary = {'a1':123, 'a2':45, 'a3':344} list_of_keys = ['a1', 'a3'] small_dictionary = dict(map(lambda key: (key, large_dictionary)。(关键,没有一个)),list_of_keys))

PS. I borrowed the .get(key, None) from a previous answer :)

我从之前的答案中借用了。get(key, None)

#8


3  

Okay, this is something that has bothered me a few times, so thank you Jayesh for asking it.

好吧,这事让我烦了好几次,谢谢你问我。

The answers above seem like as good a solution as any, but if you are using this all over your code, it makes sense to wrap the functionality IMHO. Also, there are two possible use cases here: one where you care about whether all keywords are in the original dictionary. and one where you don't. It would be nice to treat both equally.

上面的答案似乎是一个很好的解决方案,但是如果您在代码中使用了所有这些,那么包装IMHO的功能是有意义的。另外,这里有两个可能的用例:一个您关心是否所有关键字都在原字典中。一个你不知道的地方。对两者一视同仁是很好的。

So, for my two-penneth worth, I suggest writing a sub-class of dictionary, e.g.

所以,为了我的两便士的价值,我建议写一本字典的子类。

class my_dict(dict):
    def subdict(self, keywords, fragile=False):
        d = {}
        for k in keywords:
            try:
                d[k] = self[k]
            except KeyError:
                if fragile:
                    raise
        return d

Now you can pull out a sub-dictionary with

现在你可以用它来提取子字典了

orig_dict.subdict(keywords)

Usage examples:

使用例子:

#
## our keywords are letters of the alphabet
keywords = 'abcdefghijklmnopqrstuvwxyz'
#
## our dictionary maps letters to their index
d = my_dict([(k,i) for i,k in enumerate(keywords)])
print('Original dictionary:\n%r\n\n' % (d,))
#
## constructing a sub-dictionary with good keywords
oddkeywords = keywords[::2]
subd = d.subdict(oddkeywords)
print('Dictionary from odd numbered keys:\n%r\n\n' % (subd,))
#
## constructing a sub-dictionary with mixture of good and bad keywords
somebadkeywords = keywords[1::2] + 'A'
try:
    subd2 = d.subdict(somebadkeywords)
    print("We shouldn't see this message")
except KeyError:
    print("subd2 construction fails:")
    print("\toriginal dictionary doesn't contain some keys\n\n")
#
## Trying again with fragile set to false
try:
    subd3 = d.subdict(somebadkeywords, fragile=False)
    print('Dictionary constructed using some bad keys:\n%r\n\n' % (subd3,))
except KeyError:
    print("We shouldn't see this message")

If you run all the above code, you should see (something like) the following output (sorry for the formatting):

如果您运行上述所有代码,您应该会看到(类似的)以下输出(不好意思格式化):

Original dictionary:
{'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3, 'g': 6, 'f': 5, 'i': 8, 'h': 7, 'k': 10, 'j': 9, 'm': 12, 'l': 11, 'o': 14, 'n': 13, 'q': 16, 'p': 15, 's': 18, 'r': 17, 'u': 20, 't': 19, 'w': 22, 'v': 21, 'y': 24, 'x': 23, 'z': 25}

原始字典:{ a:0,' c ':2,“b”:1、“e”:4,' d ':3,“g”:6“f”:5,“我”:8,“h”:7,“k”:10“j”:9,“m”:12,“l”:11日,“o”:14日“n”:13日,“问”:16日,“p”:15日“s”:18,“r”:17日“u”:20,“t”:19日,“w”:22岁的“v”:21日“y”:24日,“x”:23日,“z”:25 }

Dictionary from odd numbered keys:
{'a': 0, 'c': 2, 'e': 4, 'g': 6, 'i': 8, 'k': 10, 'm': 12, 'o': 14, 'q': 16, 's': 18, 'u': 20, 'w': 22, 'y': 24}

字典从奇数编号的钥匙:{ a:0,' c ':2,“e”:4,“g”:6中,“我”:8“k”:10“m”:12,“o”:14日“问”:16日,“s”:18,“u”:20,“w”:22日“y”:24 }

subd2 construction fails:
original dictionary doesn't contain some keys

subd2构造失败:原来的字典不包含一些键

Dictionary constructed using some bad keys:
{'b': 1, 'd': 3, 'f': 5, 'h': 7, 'j': 9, 'l': 11, 'n': 13, 'p': 15, 'r': 17, 't': 19, 'v': 21, 'x': 23, 'z': 25}

字典构造使用一些坏键:{“b”:1、“d”:3,“f”:5,“h”:7,“j”:9,“l”:11日,“n”:13日,“p”:15日“r”:17日“t”:19日,“v”:21岁的“x”:23日,“z”:25 }

#9


1  

Yet another one (I prefer Mark Longair's answer)

还有一个(我更喜欢马克·朗伊尔的答案)

di = {'a':1,'b':2,'c':3}
req = ['a','c','w']
dict([i for i in di.iteritems() if i[0] in di and i[0] in req])

#1


272  

You could try:

你可以试试:

dict((k, bigdict[k]) for k in ('l', 'm', 'n'))

... or in Python 3 Python versions 2.7 or later (thanks to Fábio Diniz for pointing that out that it works in 2.7 too):

…或者在Python 3 Python版本2.7或更高版本中(感谢Fabio Diniz指出它在2.7中也适用):

{k: bigdict[k] for k in ('l', 'm', 'n')}

Update: As Håvard S points out, I'm assuming that you know the keys are going to be in the dictionary - see his answer if you aren't able to make that assumption. Alternatively, as timbo points out in the comments, if you want a key that's missing in bigdict to map to None, you can do:

更新:正如Havard S所指出的,我假设你知道这些键将会出现在字典中——如果你不能做出这样的假设,请查看他的答案。另外,正如timbo在评论中指出的,如果您想要将bigdict中的一个键映射为None,您可以这样做:

{k: bigdict.get(k, None) for k in ('l', 'm', 'n')}

If you're using Python 3, and you only want want keys in the new dict that actually exist in the original one, you can use the fact the view objects implement some set operations:

如果您使用的是Python 3,而您只想要在原来的版本中真正存在的新命令中需要的键,那么您可以使用视图对象实现一些集合操作的事实:

{k: bigdict[k] for k in bigdict.keys() & {'l', 'm', 'n'}}

#2


74  

A bit shorter, at least:

至少短一点:

wanted_keys = ['l', 'm', 'n'] # The keys you want
dict((k, bigdict[k]) for k in wanted_keys if k in bigdict)

#3


18  

interesting_keys = ('l', 'm', 'n')
subdict = {x: bigdict[x] for x in interesting_keys if x in bigdict}

#4


10  

This answer uses a dictionary comprehension similar to the selected answer, but will not except on a missing item.

这个答案使用一个类似于所选答案的字典理解,但不会除了一个缺失的项。

python 2 version:

python 2版本:

{k:v for k, v in bigDict.iteritems() if k in ('l', 'm', 'n')}

python 3 version:

python 3版:

{k:v for k, v in bigDict.items() if k in ('l', 'm', 'n')}

#5


8  

A bit of speed comparison for all mentioned methods:

所有上述方法的速度比较:

Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Jan 29 2016, 14:26:21) [MSC v.1500 64 bit (AMD64)] on win32
In[2]: import numpy.random as nprnd
keys = nprnd.randint(1000, size=10000)
bigdict = dict([(_, nprnd.rand()) for _ in range(1000)])

%timeit {key:bigdict[key] for key in keys}
%timeit dict((key, bigdict[key]) for key in keys)
%timeit dict(map(lambda k: (k, bigdict[k]), keys))
%timeit dict(filter(lambda i:i[0] in keys, bigdict.items()))
%timeit {key:value for key, value in bigdict.items() if key in keys}
100 loops, best of 3: 3.09 ms per loop
100 loops, best of 3: 3.72 ms per loop
100 loops, best of 3: 6.63 ms per loop
10 loops, best of 3: 20.3 ms per loop
100 loops, best of 3: 20.6 ms per loop

As it was expected: dictionary comprehensions are the best option.

正如预期的那样:字典理解是最好的选择。

#6


3  

Maybe:

可能:

subdict=dict([(x,bigdict[x]) for x in ['l', 'm', 'n']])

Python 3 even supports the following:

Python 3甚至支持以下内容:

subdict={a:bigdict[a] for a in ['l','m','n']}

Note that you can check for existence in dictionary as follows:

请注意,您可以在字典中检查是否存在如下:

subdict=dict([(x,bigdict[x]) for x in ['l', 'm', 'n'] if x in bigdict])

resp. for python 3

分别地。python 3

subdict={a:bigdict[a] for a in ['l','m','n'] if a in bigdict}

#7


3  

You can also use map (which is a very useful function to get to know anyway):

你也可以使用map(这是一个非常有用的函数来了解):

sd = dict(map(lambda k: (k, l.get(k, None)), l))

sd = dict(map(k: (k, l)得到(k,None)),l))

Example:

例子:

large_dictionary = {'a1':123, 'a2':45, 'a3':344} list_of_keys = ['a1', 'a3'] small_dictionary = dict(map(lambda key: (key, large_dictionary.get(key, None)), list_of_keys))

large_dictionary = {'a1':123, 'a2':45, 'a3':344} list_of_keys = ['a1', 'a3'] small_dictionary = dict(map(lambda key: (key, large_dictionary)。(关键,没有一个)),list_of_keys))

PS. I borrowed the .get(key, None) from a previous answer :)

我从之前的答案中借用了。get(key, None)

#8


3  

Okay, this is something that has bothered me a few times, so thank you Jayesh for asking it.

好吧,这事让我烦了好几次,谢谢你问我。

The answers above seem like as good a solution as any, but if you are using this all over your code, it makes sense to wrap the functionality IMHO. Also, there are two possible use cases here: one where you care about whether all keywords are in the original dictionary. and one where you don't. It would be nice to treat both equally.

上面的答案似乎是一个很好的解决方案,但是如果您在代码中使用了所有这些,那么包装IMHO的功能是有意义的。另外,这里有两个可能的用例:一个您关心是否所有关键字都在原字典中。一个你不知道的地方。对两者一视同仁是很好的。

So, for my two-penneth worth, I suggest writing a sub-class of dictionary, e.g.

所以,为了我的两便士的价值,我建议写一本字典的子类。

class my_dict(dict):
    def subdict(self, keywords, fragile=False):
        d = {}
        for k in keywords:
            try:
                d[k] = self[k]
            except KeyError:
                if fragile:
                    raise
        return d

Now you can pull out a sub-dictionary with

现在你可以用它来提取子字典了

orig_dict.subdict(keywords)

Usage examples:

使用例子:

#
## our keywords are letters of the alphabet
keywords = 'abcdefghijklmnopqrstuvwxyz'
#
## our dictionary maps letters to their index
d = my_dict([(k,i) for i,k in enumerate(keywords)])
print('Original dictionary:\n%r\n\n' % (d,))
#
## constructing a sub-dictionary with good keywords
oddkeywords = keywords[::2]
subd = d.subdict(oddkeywords)
print('Dictionary from odd numbered keys:\n%r\n\n' % (subd,))
#
## constructing a sub-dictionary with mixture of good and bad keywords
somebadkeywords = keywords[1::2] + 'A'
try:
    subd2 = d.subdict(somebadkeywords)
    print("We shouldn't see this message")
except KeyError:
    print("subd2 construction fails:")
    print("\toriginal dictionary doesn't contain some keys\n\n")
#
## Trying again with fragile set to false
try:
    subd3 = d.subdict(somebadkeywords, fragile=False)
    print('Dictionary constructed using some bad keys:\n%r\n\n' % (subd3,))
except KeyError:
    print("We shouldn't see this message")

If you run all the above code, you should see (something like) the following output (sorry for the formatting):

如果您运行上述所有代码,您应该会看到(类似的)以下输出(不好意思格式化):

Original dictionary:
{'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3, 'g': 6, 'f': 5, 'i': 8, 'h': 7, 'k': 10, 'j': 9, 'm': 12, 'l': 11, 'o': 14, 'n': 13, 'q': 16, 'p': 15, 's': 18, 'r': 17, 'u': 20, 't': 19, 'w': 22, 'v': 21, 'y': 24, 'x': 23, 'z': 25}

原始字典:{ a:0,' c ':2,“b”:1、“e”:4,' d ':3,“g”:6“f”:5,“我”:8,“h”:7,“k”:10“j”:9,“m”:12,“l”:11日,“o”:14日“n”:13日,“问”:16日,“p”:15日“s”:18,“r”:17日“u”:20,“t”:19日,“w”:22岁的“v”:21日“y”:24日,“x”:23日,“z”:25 }

Dictionary from odd numbered keys:
{'a': 0, 'c': 2, 'e': 4, 'g': 6, 'i': 8, 'k': 10, 'm': 12, 'o': 14, 'q': 16, 's': 18, 'u': 20, 'w': 22, 'y': 24}

字典从奇数编号的钥匙:{ a:0,' c ':2,“e”:4,“g”:6中,“我”:8“k”:10“m”:12,“o”:14日“问”:16日,“s”:18,“u”:20,“w”:22日“y”:24 }

subd2 construction fails:
original dictionary doesn't contain some keys

subd2构造失败:原来的字典不包含一些键

Dictionary constructed using some bad keys:
{'b': 1, 'd': 3, 'f': 5, 'h': 7, 'j': 9, 'l': 11, 'n': 13, 'p': 15, 'r': 17, 't': 19, 'v': 21, 'x': 23, 'z': 25}

字典构造使用一些坏键:{“b”:1、“d”:3,“f”:5,“h”:7,“j”:9,“l”:11日,“n”:13日,“p”:15日“r”:17日“t”:19日,“v”:21岁的“x”:23日,“z”:25 }

#9


1  

Yet another one (I prefer Mark Longair's answer)

还有一个(我更喜欢马克·朗伊尔的答案)

di = {'a':1,'b':2,'c':3}
req = ['a','c','w']
dict([i for i in di.iteritems() if i[0] in di and i[0] in req])