18

我的字典看起来像

d = {
  'name': 'name',
  'date': 'date',
  'amount': 'amount',
  ...
}

我想测试是否存在nameamount所以我会做

if not `name` in d and not `amount` in d:
  raise ValueError # for example

假设我从 api 获取数据,并且我想测试10字典中是否存在字段。

它仍然是寻找的最佳方式吗?

4

5 回答 5

44

您可以使用set交叉点:

if not d.viewkeys() & {'amount', 'name'}:
    raise ValueError

在 Python 3 中,这将是:

if not d.keys() & {'amount', 'name'}:
    raise ValueError

因为.keys()默认返回一个字典视图。字典视图对象(例如由.viewkeys()(和.keys()在 Python 3 中)返回的)充当集合,并且交集测试非常有效。

Python 2.7 中的演示:

>>> d = {
...   'name': 'name',
...   'date': 'date',
...   'amount': 'amount',
... }
>>> not d.viewkeys() & {'amount', 'name'}
False
>>> del d['name']
>>> not d.viewkeys() & {'amount', 'name'}
False
>>> del d['amount']
>>> not d.viewkeys() & {'amount', 'name'}
True

请注意,仅当两个键都丢失时才测试 True。如果缺少任何一个,您需要通过测试,请使用:

if not d.viewkeys() >= {'amount', 'name'}:
    raise ValueError

仅当两个键都存在时才为 False:

>>> d = {
...   'name': 'name',
...   'date': 'date',
...   'amount': 'amount',
... }
>>> not d.viewkeys() >= {'amount', 'name'}
False
>>> del d['amount']
>>> not d.viewkeys() >= {'amount', 'name'})
True

对于严格的比较(允许两个键,不多也不少),在 Python 2 中,将字典视图与集合进行比较:

if d.viewkeys() != {'amount', 'name'}:
    raise ValueError

(所以在 Python 3 中就是这样if d.keys() != {'amount', 'name'})。

于 2013-04-14T21:36:48.403 回答
11
if all(k not in d for k in ('name', 'amount')):
    raise ValueError

或者

if all(k in d for k in ('name', 'amount')):
    # do stuff
于 2013-04-14T21:35:47.910 回答
3

您也可以使用 set 为:

>>> d = {
  'name': 'name',
  'date': 'date',
  'amount': 'amount',
}
>>> test = set(['name','date'])
>>> test.issubset(set(d.keys()))
True
于 2013-04-14T21:39:51.273 回答
0

我喜欢这种形式:

>>> d = {
...   'name': 'name',
...   'date': 'date',
...   'amount': 'amount'
... }
>>> tests={'name','date'}
>>> if any(test not in d for test in tests):
...    raise ValueError
>>> # no error...

>>> del d['name']
>>> if any(test not in d for test in tests):
...    raise ValueError
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError

适用于 Py 2 或 Py 3

于 2013-04-14T22:08:42.247 回答
0

为了获得最大效率,您希望避免构造不必要的临时sets(所有非比较二元运算符都需要)。您可以这样做:

if name not in d and amount not in d:

和:

if d.keys().isdisjoint(("amount", "name")):

但这可能是错误的逻辑(在这两种情况下),因为它仅在两个if键都丢失时才进入正文(并引发异常) ,并且如果其中一个键丢失,您可能希望引发异常。

对于更可能的拒绝逻辑,d除非它包含两个键,否则您需要这样:

if name not in d or amount not in d:

这可以通过这种方式通过集合操作来完成:

首先,您需要预先定义(在函数之外避免重复构建集合):

required_keys = frozenset({"amount", "name"})

然后做:

if not d.keys() >= required_keys:

两种解决方案 (isdisjoint>=) 都避免构建每个测试临时集,并且应该尽可能高效地运行(一旦发现缺少单个键就短路,并且只需要O(1)在两个键都存在时进行查找)。就个人而言,对于只有两个键,我会坚持使用if name not in d or amount not in d:,但如果键的数量增加,当然可以使用类似集合的操作。

于 2019-03-28T00:56:23.607 回答