如何从python dict中检索密钥只是部分已知?

时间:2011-08-13 07:51:50

标签: python dictionary key substring

我有一个dict,它有一个字符串类型的键,其确切的值我不知道(因为它们是在别处动态生成的)。但是,我知道我想要的密钥包含一个特定的子字符串,并且具有此子字符串的单个密钥肯定在dict中。

检索此密钥值的最佳或“最pythonic”方法是什么?

我想到了两个策略,但两个都让我感到烦恼:

for k,v in some_dict.items():
    if 'substring' in k:
        value = v
        break

- 或 -

value = [v for (k,v) in some_dict.items() if 'substring' in k][0]

第一种方法是笨重而且有点难看,而第二种方法更清晰,但是索引到列表理解中的额外步骤([0])让我感到烦恼。是否有更好的方式来表达第二个版本,或者更简洁的方式来编写第一个版本?

5 个答案:

答案 0 :(得分:10)

可以选择使用第一个版本的性能属性编写第二个版本。

使用generator expression代替列表理解:

value = next(v for (k,v) in some_dict.iteritems() if 'substring' in k)

括号内的表达式将返回一个迭代器,然后您将要求它提供下一个,即第一个元素。没有其他元素被处理。

答案 1 :(得分:1)

这个怎么样:

value = (v for (k,v) in some_dict.iteritems() if 'substring' in k).next()

当它找到第一场比赛时会立即停止。

但它仍然具有O(n)复杂度,其中n是键值对的数量。你需要像后缀列表或后缀树这样的东西来加速搜索。

答案 2 :(得分:1)

class MyDict(dict):
    def __init__(self, *kwargs):
        dict.__init__(self, *kwargs)

    def __getitem__(self,x):
        return next(v for (k,v) in self.iteritems() if x in k)



# Defining several dicos ----------------------------------------------------    
some_dict = {'abc4589':4578,'abc7812':798,'kjuy45763':1002}

another_dict = {'boumboum14':'WSZE x478',
                'tagada4783':'ocean11',
                'maracuna102455':None}

still_another = {12:'jfg',45:'klsjgf'}



# Selecting the dicos whose __getitem__ method will be changed -------------       
name,obj = None,None
selected_dicos = [ (name,obj) for (name,obj) in globals().iteritems()
                   if type(obj)==dict
                   and all(type(x)==str for x in obj.iterkeys())]

print 'names of selected_dicos ==',[ name for (name,obj) in selected_dicos] 



# Transforming the selected dicos in instances of class MyDict -----------
for k,v in selected_dicos:
    globals()[k] = MyDict(v)



# Exemple of getting a value ---------------------------------------------      
print "some_dict['7812'] ==",some_dict['7812']

结果

names of selected_dicos == ['another_dict', 'some_dict']
some_dict['7812'] == 798

答案 3 :(得分:1)

如果有很多键,但字符串很容易从子字符串重建,那么它可以更快地重建它。例如通常你知道密钥的开头但不知道附加的日期戳。 (因此,您可能只需要尝试365个日期,而不是迭代数百万个密钥)。 情况不太可能如此,但我认为无论如何我会建议它。 e.g。

>>> names={'bob_k':32,'james_r':443,'sarah_p':12}
>>> firstname='james' #you know the substring james because you have a list of firstnames
>>> for c in "abcdefghijklmnopqrstuvwxyz":
...     name="%s_%s"%(firstname,c)
...     if name in names:
...             print name
... 
james_r

答案 4 :(得分:0)

我更喜欢第一个版本,虽然我使用some_dict.iteritems()(如果您使用的是Python 2),因为这样您就不必事先构建所有项目的完整列表。相反,你会在完成后迭代dict并中断。

在Python 3上,some_dict.items(2)已经产生了字典视图,因此它已经是一个合适的迭代器。