从上到下查找通过树(嵌套dicts)的所有路径

时间:2012-11-13 00:49:38

标签: python recursion dictionary tree

编辑:请参阅下文,了解建议的答案以及它是如何完成的。

Stack Overflow上有很多类似的问题,但没有一个像Python中那样。我是编程新手,所以请放轻松。

我有一个嵌套字典树,如下所示:

[{'word': 'The',
  'next': [{'word': 'End',
            'next': None},
           {'word': 'quick',
            'next': [{'word': 'brown',
                      'next': [{'word': 'fox',
                                'next': None}]}]},
           {'word': 'best',
            'next': [{'word': 'of',
                      'next': [{'word': 'times',
                                'next': None}]}]}]}] 

我想从上到下展平所有路径并最终得到:

[[{'word': 'The'},
  {'word': 'End'}],

 [{'word': 'The'},
  {'word': 'quick'},
  {'word': 'brown'},
  {'word': 'fox'}],

 [{'word': 'The'},
  {'word': 'best'},
  {'word': 'of'},
  {'word': 'times'}]]

我做了一个可爱的小递归函数,它首先创建了原始结构,但是我很难将其解除。这是我得到的:

def flatten_combinations(result_tree, current_combo = None, all_combos = None):
    if current_combo is None:
        current_combo = []
    if all_combos is None:
        all_combos = []
    if result_tree is None:
        all_combos.append(current_combo)
        return
    for word in result_tree:
        current_combo.append({'word': word['word']})
        flatten_combinations(word['next'], current_combo, all_combos)
    return current_combo

...返回此信息:

[{'word': 'The'},
 {'word': 'End'},
 {'word': 'quick'},
 {'word': 'brown'},
 {'word': 'fox'},
 {'word': 'best'},
 {'word': 'of'},
 {'word': 'times'}]

......显然有些接近但不太正确。

我知道这个功能可能非常恐怖,但我正在自学编程,所以我甚至都没有尝试利用可能存在的语言功能让我从头开始思考这些东西(“他说,发布到Q& A网站,希望其成员能帮助他省略一些想法)。

那么:我做错了什么?

编辑:Moshe在下面纠正了几个问题:

def flatten_combinations(result_tree, current_combo = None, all_combos = None):
    if current_combo is None:
        current_combo = []
    if all_combos is None:
        all_combos = []
    if result_tree is None:
        all_combos.append(current_combo)
        return
    for word in result_tree:
        current_combo = current_combo[:]
        current_combo.append({'word': word['word']})
        flatten_combinations(word['next'], current_combo, all_combos)
    return all_combos 

现在距离更近了,但不是很正确:

[{'word': 'The'}, 
 {'word': 'End'}],

[{'word': 'The'},
 {'word': 'End'},
 {'word': 'quick'},
 {'word': 'brown'},
 {'word': 'fox'}],

[{'word': 'The'},
 {'word': 'End'},
 {'word': 'quick'},
 {'word': 'best'},
 {'word': 'of'},
 {'word': 'times'}]]

4 个答案:

答案 0 :(得分:1)

如果在递归调用中传入current_combo的副本,那么在for循环的下一次迭代中不会丢失当前路径。

此外,您不需要返回current_combo,因为结果不用于递归。您可能希望返回all_combos而不是将其作为参数。或者,您可以使用递归函数而不使用递归函数,使用非递归函数为all_combos创建列表并将其传递给递归函数,以便递归函数可以假设all_combos已设置。

答案 1 :(得分:1)

我采取这种策略:对于每棵树,

  1. 递归以计算此树根处的单词后面的句子列表。
  2. 对于每个句子,在它前面添加当前单词。
  3. 返回新扩展的句子列表。
  4. 您是否通过归纳进行了校对?我觉得归纳是我编程中最有用的数学技巧之一:

    1. 证明您的函数正确处理了“next”为None的树。
    2. 证明您的函数处理深度为n的树,假设它可以正确处理深度为n-1的树。
    3. 归纳然后扩展证据以覆盖任何深度的树木。完成!

答案 2 :(得分:1)

有两个小错误:

1)您返回current_combo而不是all_combos。这只会给你最后的结果

2)在每次迭代上,修改current_combo。先复制一份!

new_current_combo = current_combo[:]
new_current_combo.append({'word': word['word']})
flatten_combinations(word['next'], new_current_combo, all_combos)

完整代码:

def flatten_combinations(result_tree, current_combo=None, all_combos=None):
    if current_combo is None:
        current_combo = []
    if all_combos is None:
        all_combos = []
    if result_tree is None:
        all_combos.append(current_combo)
        return
    for word in result_tree:
        new_current_combo = current_combo[:]
        new_current_combo.append({'word': word['word']})
        flatten_combinations(word['next'], new_current_combo, all_combos)
    return all_combos 

答案 3 :(得分:0)

让@JoshHeitzman的答案具体化(并简化你的默认参数):

def flatten_combinations(result_tree, current_combo = [], all_combos = []):
if result_tree is None:
    all_combos.append(current_combo)
    return
for word in result_tree:
    current_combo.append({'word': word['word']})
    flatten_combinations(word['next'], current_combo[:], all_combos)
return all_combos