我有一个巨大的词典,里面有很多嵌套的词汇 - 就像一棵巨树,深度未知。
我需要一个像find_value()
这样的函数,它接受 dict,value(作为字符串),并返回列表列表,每个函数都有一个是“路径”(从第一个键到键的顺序链键(或键值)和找到的值)。如果找不到任何内容,则返回空列表。
我写了这段代码:
def find_value(dict, sought_value, current_path, result):
for key,value in dict.items():
current_path.pop()
current_path.append(key)
if sought_value in key:
result.append(current_path)
if type(value) == type(''):
if sought_value in value:
result.append(current_path+[value])
else:
current_path.append(key)
result = find_value(value, sought_value, current_path, result)
current_path.pop()
return result
我将此功能称为测试:
result = find_value(self.dump, sought_value, ['START_KEY_FOR_DELETE'], [])
if not len(result):
print "forgive me, mylord, i'm afraid we didn't find him.."
elif len(result) == 1:
print "bless gods, for all that we have one match, mylord!"
由于一些莫名其妙的原因,我的一些测试失败了。我开始调试并发现,即使 current_path 打印出正确的东西(它总是这样,我检查了!),结果也莫名其妙地被破坏了。也许是因为递归魔术?
任何人都可以帮我解决这个问题吗?也许我的任务有一个简单的解决方案?
答案 0 :(得分:2)
当你写result.append(current_path)
时,你不是在复制current_path
,而是继续变异。将其更改为result.append(current_path[:])
。
答案 1 :(得分:1)
我怀疑你能做多少优化这样的递归搜索。假设在同一个字典上有很多查找,并且字典在加载后不会更改,那么您可以将其编入索引以获得O(1)查找...
def build_index(src, dest, path=[]):
for k, v in src.iteritems():
fk = path+[k]
if isinstance(v, dict):
build_index(v, dest, fk)
else:
try:
dest[v].append(fk)
except KeyError:
dest[v] = [fk]
>>> data = {'foo': {'sub1': 'blah'}, 'bar': {'sub2': 'whatever'}, 'baz': 'blah'}
>>> index = {}
>>> build_index(data, index)
>>> index
{'blah': [['baz'], ['foo', 'sub1']], 'whatever': [['bar', 'sub2']]}
>>> index['blah']
[['baz'], ['foo', 'sub1']]