有没有更快的解决方案来解决这类工作?

时间:2013-09-16 01:47:14

标签: python performance dictionary hashmap

在下面给出一个元组:

({15: None}, 
{7: None}, 
{2: None, 3: None, 4: None, 7: None, 13: None, 15: None}, 
{13: None}, 
{4: None}, 
{7: None}, 
{15: None}, 
{15: None, 4: None, 13: None, 7: None}, 
{15: None, 4: None, 7: None}, 
{7: None}, 
{4: None}, 
{4: None}, 
{4: None, 7: None}, 
{4: None})

算法:

for tail in xrange(len(tupe_above), -1, -1):
   for _ in tuple_above[tail].iteritems():
      for head in xrange(0, tail):         
         if _[0] in head:
            print 'got one ...'

问题:

我心中有强烈的感觉,必须有一种方法可以在线性时间内完成这项工作(假设使用更高层的字典),任何人都可以给我一个建议吗?感谢。

2 个答案:

答案 0 :(得分:1)

我会尽力理解你的问题。您是否尝试从此元组中查找包含给定键(例如dict)的所有18

我认为最具Pythonic的解决方案应该是针对此特定嵌套级别的线性时间:

def getDictsWithKey(dictTuple, key):
    return [d for d in dictTuple if key in d]

答案 1 :(得分:1)

我不确定我理解你的“工作描述”,但我认为你想要这个:

def find_matches(tuple_of_dicts, key_to_find):
    return [d for d in tuple_of_dicts if key_to_find in d]

所以:

>>> tuple_of_dicts = ({18: None}, {10: None}, {16: None, 18: None, 5: None, 6: None, 7: None, 10: None}, {16: None}, {7: None}, {10: None}, {18: None}, {16: None, 10: None, 18: None, 7: None}, {10: None, 18: None, 7: None}, {10: None}, {7: None}, {7: None}, {10: None, 7: None}, {7: None})
>>> find_matches(tuple_of_dicts, 18)
[{18: None},
 {5: None, 6: None, 7: None, 10: None, 16: None, 18: None},
 {18: None},
 {7: None, 10: None, 16: None, 18: None},
 {7: None, 10: None, 18: None}]

这适用于线性时间。如果你的元组有N个dicts,平均每个M个成员,你走元组,为每次迭代做一个恒定时间的dict查找,总共为O(N)。


但如果您要进行大量此类搜索,那么您甚至可以比线性时间更好地

诀窍是(听起来你可能已经怀疑过)构建一个索引字典,将每个键映射到它所在的字典的索引,或者仅映射到字典本身。例如:

>>> dict_of_dicts = {}
>>> for d in tuple_of_dicts:
...     for key in d:
...         dict_of_dicts.setdefault(key, []).append(d)
>>> def find_matches(dict_of_dicts, key_to_find):
...     return dict_of_dicts[key_to_find]

这需要O(N * M)时间进行设置工作,并构建一个O(N * M)空间的字典*,但它是每次搜索的简单O(1)字典查找。所以,只要你做的不仅仅是M次搜索,而且你可以负担得起额外的空间,那将是一个巨大的收获。


*确切地说:如果你有L个不同的键,M个总键,你在dict中进行N * M个查找,向dict添加N * M / L,并且N * M附加到M / L长度列表。由于列表附加是分摊的常数时间,因此是O(N * M + N * M / L + N * M)= O(N * M)设置时间。同时,dict是O(N * L)空间,每个成员是长度为O(M / L)的列表,因此用于列表的总空间为O(N * L * M / L)= O( N * M),并且dict及其列表的总空间是O(N * L + N * M)= O(N * M)。最后,搜索只是散列值,在dict中查找它,并返回对M / L长度列表的引用,所有这些都是常量操作,因此每次搜索都是O(1)。