问题:如何在一次通过中检查多个键是否在字典中?
我想做类似的事情:
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
if ("foo","bar") in foo:
#do stuff
如何检查dict foo中是否同时包含“ foo”和“ bar”?
I want to do something like:
foo = {
'foo': 1,
'zip': 2,
'zam': 3,
'bar': 4
}
if ("foo", "bar") in foo:
#do stuff
How do I check whether both foo
and bar
are in dict foo
?
回答 0
好吧,你可以这样做:
>>> if all (k in foo for k in ("foo","bar")):
... print "They're there!"
...
They're there!
Well, you could do this:
>>> if all (k in foo for k in ("foo","bar")):
... print "They're there!"
...
They're there!
回答 1
if {"foo", "bar"} <= myDict.keys(): ...
如果您仍在使用Python 2,则可以执行
if {"foo", "bar"} <= myDict.viewkeys(): ...
如果您仍然使用的是旧版本<= 2.6的Python,则可以调用set
dict,但是它将遍历整个dict以构建集合,这很慢:
if set(("foo", "bar")) <= set(myDict): ...
if {"foo", "bar"} <= myDict.keys(): ...
If you’re still on Python 2, you can do
if {"foo", "bar"} <= myDict.viewkeys(): ...
If you’re still on a really old Python <= 2.6, you can call set
on the dict, but it’ll iterate over the whole dict to build the set, and that’s slow:
if set(("foo", "bar")) <= set(myDict): ...
回答 2
3个替代方案的简单基准测试平台。
输入您自己的D和Q值
>>> from timeit import Timer
>>> setup='''from random import randint as R;d=dict((str(R(0,1000000)),R(0,1000000)) for i in range(D));q=dict((str(R(0,1000000)),R(0,1000000)) for i in range(Q));print("looking for %s items in %s"%(len(q),len(d)))'''
>>> Timer('set(q) <= set(d)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632499
0.28672504425048828
#This one only works for Python3
>>> Timer('set(q) <= d.keys()','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632084
2.5987625122070312e-05
>>> Timer('all(k in d for k in q)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632219
1.1920928955078125e-05
Simple benchmarking rig for 3 of the alternatives.
Put in your own values for D and Q
>>> from timeit import Timer
>>> setup='''from random import randint as R;d=dict((str(R(0,1000000)),R(0,1000000)) for i in range(D));q=dict((str(R(0,1000000)),R(0,1000000)) for i in range(Q));print("looking for %s items in %s"%(len(q),len(d)))'''
>>> Timer('set(q) <= set(d)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632499
0.28672504425048828
#This one only works for Python3
>>> Timer('set(q) <= d.keys()','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632084
2.5987625122070312e-05
>>> Timer('all(k in d for k in q)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632219
1.1920928955078125e-05
回答 3
您不必将左侧包裹在一组中。您可以这样做:
if {'foo', 'bar'} <= set(some_dict):
pass
这也比all(k in d...)
解决方案要好。
You don’t have to wrap the left side in a set. You can just do this:
if {'foo', 'bar'} <= set(some_dict):
pass
This also performs better than the all(k in d...)
solution.
回答 4
使用集:
if set(("foo", "bar")).issubset(foo):
#do stuff
或者:
if set(("foo", "bar")) <= set(foo):
#do stuff
Using sets:
if set(("foo", "bar")).issubset(foo):
#do stuff
Alternatively:
if set(("foo", "bar")) <= set(foo):
#do stuff
回答 5
这个怎么样:
if all([key in foo for key in ["foo","bar"]]):
# do stuff
pass
How about this:
if all([key in foo for key in ["foo","bar"]]):
# do stuff
pass
回答 6
我认为这是最明智的选择。
{'key1','key2'} <= my_dict.keys()
I think this is the smartest and pithonic.
{'key1','key2'} <= my_dict.keys()
回答 7
虽然我喜欢Alex Martelli的答案,但对我来说似乎不是Pythonic。也就是说,我认为成为Pythonic的重要部分是易于理解。有了这个目标,<=
并不容易理解。
虽然字符更多,但issubset()
按照卡尔·福格特兰(Karl Voigtland)的答案所建议的用法更容易理解。由于该方法可以将字典用作参数,因此一个简短的,可理解的解决方案是:
foo = {'foo': 1, 'zip': 2, 'zam': 3, 'bar': 4}
if set(('foo', 'bar')).issubset(foo):
#do stuff
我想用{'foo', 'bar'}
代替set(('foo', 'bar'))
,因为它更短。但是,这不是很容易理解,我认为花括号像字典一样容易被混淆。
While I like Alex Martelli’s answer, it doesn’t seem Pythonic to me. That is, I thought an important part of being Pythonic is to be easily understandable. With that goal, <=
isn’t easy to understand.
While it’s more characters, using issubset()
as suggested by Karl Voigtland’s answer is more understandable. Since that method can use a dictionary as an argument, a short, understandable solution is:
foo = {'foo': 1, 'zip': 2, 'zam': 3, 'bar': 4}
if set(('foo', 'bar')).issubset(foo):
#do stuff
I’d like to use {'foo', 'bar'}
in place of set(('foo', 'bar'))
, because it’s shorter. However, it’s not that understandable and I think the braces are too easily confused as being a dictionary.
回答 8
Alex Martelli的解决方案set(queries) <= set(my_dict)
是最短的代码,但可能不是最快的。假设Q = len(查询)和D = len(my_dict)。
这需要O(Q)+ O(D)来创建两个集合,然后(一个希望!)仅O(min(Q,D))进行子集测试-当然,假设Python进行了查找是O(1)-这是最坏的情况(当答案为True时)。
休格布朗(et al?)的生成器解all(k in my_dict for k in queries)
为最坏情况O(Q)。
复杂因素:
(1)基于集合的小工具中的循环全部以C速度完成,而基于Any的小工具则在字节码上循环。
(2)基于任何内容的小工具的调用者都可以使用任何失败概率的知识来对查询项目进行相应的排序,而基于集合的小工具则不允许这样的控制。
与往常一样,如果速度很重要,则在操作条件下进行基准测试是一个好主意。
Alex Martelli’s solution set(queries) <= set(my_dict)
is the shortest code but may not be the fastest. Assume Q = len(queries) and D = len(my_dict).
This takes O(Q) + O(D) to make the two sets, and then (one hopes!) only O(min(Q,D)) to do the subset test — assuming of course that Python set look-up is O(1) — this is worst case (when the answer is True).
The generator solution of hughdbrown (et al?) all(k in my_dict for k in queries)
is worst-case O(Q).
Complicating factors:
(1) the loops in the set-based gadget are all done at C-speed whereas the any-based gadget is looping over bytecode.
(2) The caller of the any-based gadget may be able to use any knowledge of probability of failure to order the query items accordingly whereas the set-based gadget allows no such control.
As always, if speed is important, benchmarking under operational conditions is a good idea.
回答 9
您可以使用.issubset()以及
>>> {"key1", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
True
>>> {"key4", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
False
>>>
You can use .issubset() as well
>>> {"key1", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
True
>>> {"key4", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
False
>>>
回答 10
使用lambda怎么样?
if reduce( (lambda x, y: x and foo.has_key(y) ), [ True, "foo", "bar"] ): # do stuff
How about using lambda?
if reduce( (lambda x, y: x and foo.has_key(y) ), [ True, "foo", "bar"] ): # do stuff
回答 11
如果您想:
然后:
from operator import itemgetter
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
keys = ("foo","bar")
getter = itemgetter(*keys) # returns all values
try:
values = getter(foo)
except KeyError:
# not both keys exist
pass
In case you want to:
- also get the values for the keys
- check more than one dictonary
then:
from operator import itemgetter
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
keys = ("foo","bar")
getter = itemgetter(*keys) # returns all values
try:
values = getter(foo)
except KeyError:
# not both keys exist
pass
回答 12
并不是说这不是您没有想到的事情,但是我发现最简单的事情通常是最好的:
if ("foo" in foo) and ("bar" in foo):
# do stuff
Not to suggest that this isn’t something that you haven’t thought of, but I find that the simplest thing is usually the best:
if ("foo" in foo) and ("bar" in foo):
# do stuff
回答 13
>>> if 'foo' in foo and 'bar' in foo:
... print 'yes'
...
yes
Jason()在Python中不是必需的。
>>> if 'foo' in foo and 'bar' in foo:
... print 'yes'
...
yes
Jason, () aren’t necessary in Python.
回答 14
就我的观点而言,所有给定的选项都有两种易于理解的方法。因此,我的主要标准是具有非常易读的代码,而不是非常快速的代码。为了使代码易于理解,我更喜欢给定可能性:
- var <= var2.keys()
- var.issubset(var2)
在下面的测试中,“ var <= var2.keys()”的执行速度更快,这一事实我更喜欢。
import timeit
timeit.timeit('var <= var2.keys()', setup='var={"managed_ip", "hostname", "fqdn"}; var2= {"zone": "test-domain1.var23.com", "hostname": "bakje", "api_client_ip": "127.0.0.1", "request_data": "", "request_method": "GET", "request_url": "hvar2p://127.0.0.1:5000/test-domain1.var23.com/bakje", "utc_datetime": "04-Apr-2019 07:01:10", "fqdn": "bakje.test-domain1.var23.com"}; var={"managed_ip", "hostname", "fqdn"}')
0.1745898080000643
timeit.timeit('var.issubset(var2)', setup='var={"managed_ip", "hostname", "fqdn"}; var2= {"zone": "test-domain1.var23.com", "hostname": "bakje", "api_client_ip": "127.0.0.1", "request_data": "", "request_method": "GET", "request_url": "hvar2p://127.0.0.1:5000/test-domain1.var23.com/bakje", "utc_datetime": "04-Apr-2019 07:01:10", "fqdn": "bakje.test-domain1.var23.com"}; var={"managed_ip", "hostname", "fqdn"};')
0.2644960229999924
Just my take on this, there are two methods that are easy to understand of all the given options. So my main criteria is have very readable code, not exceptionally fast code. To keep code understandable, i prefer to given possibilities:
- var <= var2.keys()
- var.issubset(var2)
The fact that “var <= var2.keys()” executes faster in my testing below, i prefer this one.
import timeit
timeit.timeit('var <= var2.keys()', setup='var={"managed_ip", "hostname", "fqdn"}; var2= {"zone": "test-domain1.var23.com", "hostname": "bakje", "api_client_ip": "127.0.0.1", "request_data": "", "request_method": "GET", "request_url": "hvar2p://127.0.0.1:5000/test-domain1.var23.com/bakje", "utc_datetime": "04-Apr-2019 07:01:10", "fqdn": "bakje.test-domain1.var23.com"}; var={"managed_ip", "hostname", "fqdn"}')
0.1745898080000643
timeit.timeit('var.issubset(var2)', setup='var={"managed_ip", "hostname", "fqdn"}; var2= {"zone": "test-domain1.var23.com", "hostname": "bakje", "api_client_ip": "127.0.0.1", "request_data": "", "request_method": "GET", "request_url": "hvar2p://127.0.0.1:5000/test-domain1.var23.com/bakje", "utc_datetime": "04-Apr-2019 07:01:10", "fqdn": "bakje.test-domain1.var23.com"}; var={"managed_ip", "hostname", "fqdn"};')
0.2644960229999924
回答 15
在确定是否只有某些键匹配的情况下,这可行:
any_keys_i_seek = ["key1", "key2", "key3"]
if set(my_dict).intersection(any_keys_i_seek):
# code_here
pass
查找是否只有一些键匹配的另一种选择:
any_keys_i_seek = ["key1", "key2", "key3"]
if any_keys_i_seek & my_dict.keys():
# code_here
pass
In the case of determining whether only some keys match, this works:
any_keys_i_seek = ["key1", "key2", "key3"]
if set(my_dict).intersection(any_keys_i_seek):
# code_here
pass
Yet another option to find if only some keys match:
any_keys_i_seek = ["key1", "key2", "key3"]
if any_keys_i_seek & my_dict.keys():
# code_here
pass
回答 16
用于检测所有键是否都在字典中的另一个选项:
dict_to_test = { ... } # dict
keys_sought = { "key_sought_1", "key_sought_2", "key_sought_3" } # set
if keys_sought & dict_to_test.keys() == keys_sought:
# yes -- dict_to_test contains all keys in keys_sought
# code_here
pass
Another option for detecting whether all keys are in a dict:
dict_to_test = { ... } # dict
keys_sought = { "key_sought_1", "key_sought_2", "key_sought_3" } # set
if keys_sought & dict_to_test.keys() == keys_sought:
# True -- dict_to_test contains all keys in keys_sought
# code_here
pass
回答 17
>>> ok
{'five': '5', 'two': '2', 'one': '1'}
>>> if ('two' and 'one' and 'five') in ok:
... print "cool"
...
cool
这似乎有效
>>> ok
{'five': '5', 'two': '2', 'one': '1'}
>>> if ('two' and 'one' and 'five') in ok:
... print "cool"
...
cool
This seems to work
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。