简体   繁体   English

Python遍历嵌套字典

[英]Python iterating through nested dictionaries

First of all, here is the question and the code written: 首先,这里是问题和编写的代码:

def family_lineage(familytree, lineage):
    '''(dict, list of strs) -> boolean
    Return True if lineage specifies a list of names who are directly related
    in a chain of parent-child relationships, and NOT child-parent, parent-grandchild..etc,
    beginning from the first generation listed.

    >>> trace_lineage({'Gina': {'Sam': {'Tina': {}},
                           'Li': {}},
                   'Guy': {}},
                      ['Gina'])
    True

    >>> trace_lineage({'Gina': {'Sam': {'Tina': {}},
                               'Li': {}},
                       'Guy': {}},
                      ['Gina', 'Sam', 'Tina'])
    True
    >>> trace_lineage({'Gina': {'Sam': {'Tina': {}},
                               'Li': {}},
                       'Guy': {}},
                      ['Gina', 'Tina'])
    False
    '''

So, in the above example, it shows the 'Guy' has no children, and 'Gina' has two children, 'Sam', and 'Li'. 因此,在上面的示例中,它显示“ Guy”没有孩子,而“ Gina”有两个孩子“ Sam”和“ Li”。 'Sam' has one child, 'Tina'. “山姆”有一个孩子“蒂娜”。

for k, v in familytree.items():
    for n, m in v.items():
        if lineage[0] == any(k) and len(lineage) == 1:
            return True
        elif lineage[0] == k and lineage[1] == n and len(lineage) ==2:
            return True
        elif lineage[0] == k and lineage[1] == n and lineage[2] == m and \
        len(lineage) == 3:
            return True
        else:
            return False

So, my question is, how would I write this if the familytree extended beyond three generations? 因此,我的问题是,如果家族树扩展到三代以上,我将如何写呢? Is there a more concise way of writing this code? 有没有更简洁的代码编写方式?

Here is an iterative approach that will work even if lineage does not start at the top of the family tree: 这是一种迭代方法,即使lineage不是从家族树的顶部开始,也可以使用:

def family_lineage(familytree, lineage):
    trees = [familytree]
    while trees:
        tree = trees.pop()
        trees.extend(t for t in tree.values() if t)
        for name in lineage:
            if name not in tree:
                break
            tree = tree[name]
        else:
            return True
    return False

Basically, you want to see if you can traverse the tree; 基本上,您想看看是否可以遍历树。 use reduce() to loop over the elements and if a KeyError is raised, the path doesn't exist: 使用reduce()遍历元素,如果引发KeyError ,则该路径不存在:

def family_lineage(familytree, lineage):
    if not familytree:
        return False
    try:
        reduce(lambda d, k: d[k], lineage, familytree)
        return True
    except KeyError:
        # No match at this level, recurse down the family tree
        return any(family_lineage(val, lineage) for val in familytree.itervalues())

reduce() applies the lambda function recursively to lineage , starting with familytree . reduce()familytree开始,递归地将lambda函数应用于lineage

To support finding lineages deeper down the tree, you need to recurse down the tree on KeyError s. 为了支持寻找更深层次的谱系树倒,则需要向下递归在树上KeyError秒。

Demo: 演示:

>>> tree = {'Gina': {'Sam': {'Tina': {}}, 'Li': {}}, 'Guy': {}}
>>> family_lineage(tree, ['Gina'])
True
>>> family_lineage(tree, ['Gina', 'Sam', 'Tina'])
True
>>> family_lineage(tree, ['Gina', 'Tina'])
False
>>> family_lineage(tree, ['Sam', 'Tina'])
True

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM