35

我想知道:是否可以使用不完整的键访问 dict 值(只要给定字符串的条目不超过一个)?例如:

my_dict = {'name': 'Klauss', 'age': 26, 'Date of birth': '15th july'}
print my_dict['Date']
>> '15th july'

这可能吗?怎么可能做到?

4

7 回答 7

66

您不能直接使用 执行此操作dict[keyword],您必须遍历 dict 并将每个键与关键字匹配,如果找到关键字则返回相应的值。这将是一次O(N)手术。

>>> my_dict = {'name': 'Klauss', 'age': 26, 'Date of birth': '15th july'}
>>> next(v for k,v in my_dict.items() if 'Date' in k)
'15th july'

要获取所有这些值,请使用列表推导:

>>> [ v for k,v in my_dict.items() if 'Date' in k]
['15th july']

str.startswith如果您只想要那些键以“日期”开头的值,请使用:

>>> next( v for k,v in my_dict.items() if k.startswith('Date'))
'15th july'
>>> [ v for k,v in my_dict.items() if k.startswith('Date')]
['15th july']
于 2013-06-14T10:53:42.740 回答
8

不是最好的解决方案,可以改进(覆盖getitem

class mydict(dict):
    def __getitem__(self, value):
        keys = [k for k in self.keys() if value in k]
        key = keys[0] if keys else None
        return self.get(key)


my_dict = mydict({'name': 'Klauss', 'age': 26, 'Date of birth': '15th july'})
print(my_dict['Date'])# returns 15th july
于 2013-06-14T11:24:55.027 回答
6

当然有可能:

print next(val for key, val in my_dict.iteritems() if key.startswith('Date'))

但这会导致对字典进行全面扫描。它只找到第一个这样的匹配键(其中“第一个”是任意的)并引发StopIteration而不是KeyError如果没有键匹配。

为了更接近您的想法,最好将其编写为函数:

def value_by_key_prefix(d, partial):
    matches = [val for key, val in d.iteritems() if key.startswith(partial)]
    if not matches:
        raise KeyError(partial)
    if len(matches) > 1:
        raise ValueError('{} matches more than one key'.format(partial))
    return matches[0]
于 2013-06-14T10:54:06.700 回答
4

您可以使用内置的过滤器功能根据特定条件过滤字典、列表等。

filtered_dict = dict(filter(lambda item: "Date" in item[0], my_dict.items()))

优点是您可以将它用于不同的数据结构。

于 2019-04-18T05:01:21.203 回答
2
>>> my_dict = {'name': 'Klauss', 'age': 26, 'Date of birth': '15th july'}
>>> next(v for k,v in my_dict.items() if 'Date' in k)
'15th july'


>>> [ v for k,v in my_dict.items() if 'Date' in k]
['15th july']


>>> next( v for k,v in my_dict.items() if k.startswith('Date'))
'15th july'
>>> [ v for k,v in my_dict.items() if k.startswith('Date')]
['15th july']

如果我使用上面给定的方法,我会得到 StopIteration 异常

于 2014-12-17T04:43:14.757 回答
1

您并不是在建议一个连贯的 API:

  1. 结果应该是什么my_dict['']?您没有一对一的映射。
  2. 它应该如何扩展到除 之外的类型str

另一个你不能直接使用它的原因,即使对于字符串并且假设你总是返回一个列表,是因为 Pythondict是使用哈希表实现的,它会映射xyxz表中不相关的单元格。

所以,换一种方式:这样的查找意味着要更慢地实现dict, (这没有意义,针对不常见的用途进行优化)或者像全扫描一样慢 - 你不妨写它手动,因为值得专门的便捷方法并不常见。

于 2013-06-14T11:01:55.537 回答
0

在 pywinauto 中有一个“模糊”字典的漂亮而聪明的实现——这可能非常适合你在这里需要的东西。

https://code.google.com/p/pywinauto/source/browse/pywinauto/fuzzydict.py

和这里的文档:http: //pywinauto.googlecode.com/hg/pywinauto/docs/code/pywinauto.fuzzydict.html

(编辑:虽然如果您特别想从键的开头进行匹配,您可能需要用您的自定义代码替换 SequenceMatcher 逻辑)

于 2013-06-14T11:34:51.357 回答