Python 将字典树转换为多维列表

Python 将字典树转换为多维列表,python,dictionary,multidimensional-array,Python,Dictionary,Multidimensional Array,我有一本类似Python的字典: {'G': {'G': {'T': {'A': 'end'}, 'C': 'end'}, }, 'C': {'G': 'end'} } 如何将其转换为这样的多维数组 ['G', ['G', ['T', ['A'], 'C'] ], 'C', ['G'] ] 多谢各位 d = {

我有一本类似Python的字典:

{'G': 
     {'G': 
          {'T': 
               {'A': 'end'},
          'C': 'end'},
     }, 
 'C': {'G': 'end'}
}
如何将其转换为这样的多维数组

['G', 
      ['G', 
          ['T', ['A'],
           'C']
       ], 
  'C', ['G'] 
]
多谢各位

d = {
 'G': 
     {'G': 
          {'T': 
               {'A': {'$': '$'}},
          'C': {'$': '$'}}
     }, 
 'C': {'G': {'$': '$'}}
}

def merge(dct):
    return [[k] + merge(v) for k,v in dct.items() if isinstance(v, dict)]

>>> merge(d)
[['C', ['G']], ['G', ['G', ['C'], ['T', ['A']]]]]
还有一个变体:

def merge(dct):
    l = []
    for k,v in dct.items():
        if isinstance(v, dict):
            l.append(k)
            m = merge(v)
            if m:
                l.append(m)
    return l


>>> merge(d)
['C', ['G'], 'G', ['G', ['C', 'T', ['A']]]]
还有一个变体:

def merge(dct):
    l = []
    for k,v in dct.items():
        if isinstance(v, dict):
            l.append(k)
            m = merge(v)
            if m:
                l.append(m)
    return l


>>> merge(d)
['C', ['G'], 'G', ['G', ['C', 'T', ['A']]]]

首先,我假设您不关心字典中键的顺序,因为字典是无序的。如果您真的在意,那么除非您改用collections.OrderedDict或等效工具,否则没有解决方案可以完全满足您的需求

第二,尽管您现在使用字符串“end”作为sentinel值来指示处理应该停止的位置,但没有迹象表明我们应该对任何不是字典的值进行进一步处理。代码可以修改以适应其他类型的递归,但是现在我们将保持它的简单性,只需跳过树中的所有非字典值,尽管我们将处理它们的键

有了这些假设,我将使用一对递归函数来实现这一点。在本例中,编写了转换,以便您可以在需要时将这种模式与其他转换函数一起使用。转换的操作比列表理解要复杂一些,因为在某种意义上,我们将结果列表拼接到输出列表中,稍微平展输出

d = {
    'G': {'G': 
            {'T': 
                {'A': 'end'},
             'C': 'end'}
         }, 
    'C': {'G': 'end'}
}

# Transform a dictionary to a list using the given transformation function.
# The transformation function must take a key and value and return a sequence,
# which will be spliced into the output list. No ordering is imposed on the
# keys of the dictionary.
def transform(d, f):
    out = []
    for k, v in d.iteritems():
        out.extend(f(k, v))
    return out

def nested_dict_to_list(key, value):
    if not isinstance(value, dict):
        # don't recurse into this value
        return [key]
    else:
        return [key, transform(value, nested_dict_to_list)]


>>> transform(d, nested_dict_to_list)
['C', ['G'], 'G', ['G', ['C', 'T', ['A']]]]

编辑:这个问题以前使用{'$':'$'}作为哨兵值,但现在只使用'end';相应地更新代码。

首先,我假设您不关心字典中键的顺序,因为字典是无序的。如果您真的在意,那么除非您改用collections.OrderedDict或等效工具,否则没有解决方案可以完全满足您的需求

第二,尽管您现在使用字符串“end”作为sentinel值来指示处理应该停止的位置,但没有迹象表明我们应该对任何不是字典的值进行进一步处理。代码可以修改以适应其他类型的递归,但是现在我们将保持它的简单性,只需跳过树中的所有非字典值,尽管我们将处理它们的键

有了这些假设,我将使用一对递归函数来实现这一点。在本例中,编写了转换,以便您可以在需要时将这种模式与其他转换函数一起使用。转换的操作比列表理解要复杂一些,因为在某种意义上,我们将结果列表拼接到输出列表中,稍微平展输出

d = {
    'G': {'G': 
            {'T': 
                {'A': 'end'},
             'C': 'end'}
         }, 
    'C': {'G': 'end'}
}

# Transform a dictionary to a list using the given transformation function.
# The transformation function must take a key and value and return a sequence,
# which will be spliced into the output list. No ordering is imposed on the
# keys of the dictionary.
def transform(d, f):
    out = []
    for k, v in d.iteritems():
        out.extend(f(k, v))
    return out

def nested_dict_to_list(key, value):
    if not isinstance(value, dict):
        # don't recurse into this value
        return [key]
    else:
        return [key, transform(value, nested_dict_to_list)]


>>> transform(d, nested_dict_to_list)
['C', ['G'], 'G', ['G', ['C', 'T', ['A']]]]


编辑:这个问题以前使用{'$':'$'}作为哨兵值,但现在只使用'end';相应地更新代码。

如果“C”与dict中的G处于同一级别,为什么它在列表中不处于同一级别?我编辑了它,希望它现在有意义所有的“$”都发生了什么?您想要的输出不是有效的Python列表;支架不匹配。这是因为你在结尾忘了一个“],还是因为你[在开头]有一个额外的“?”很好的观点。我把它看作是一个额外的“?”[,但这种不一致性很重要。如果“C”与dict中的G处于同一级别,为什么它在列表中不处于同一级别?我编辑了它,希望它现在有意义所有的“$”都发生了什么?您想要的输出不是有效的Python列表;大括号不匹配。这是因为您最后忘记了a],还是因为您有一个额外的[一开始?很好,我把它当作额外的阅读[,但这种不一致性很明显。很接近,也许足够接近,但有两个差异:1我们假设顺序无关紧要;2结构有点不一致,因为上面写的相邻键是同一个列表的一部分;也就是说,根据您的顺序,Federico想要的答案是['C'、['G']、['G'、['G'、['C'、['t'、['a']]].在'A'和'C'下的子目录{'$':'$'}发生了什么事?我认为您的理解应该是:def treedct:return[[k]+treev if is instancev,dict else[k]for k,v in dct.items]哎呀,由于上面提到的不一致性,我的结构不太正确。我认为第二个变体更有意义。@dawg有问题,作者希望结果列表不带$,但我同意youClose,也许足够接近,但有两个差异:1我们假设顺序无关紧要;2结构有点不一致,如neiGhoring键写在上面是为了成为同一个列表的一部分;也就是说,按照您的顺序,Federico想要的答案是['C'、['G'、['G'、['C'、['T'、['A'\\\\\\\\\\].“'A'和'C'下的子目录{'$':'$}发生了什么事?我认为您的理解应该是:如果安装,返回[[k]+treev哎呀,由于上面提到的不一致性,我的结构不太正确。我认为第二个变体更有意义。@dawg有问题,作者希望结果列表不带$,但我同意你的看法,子目录{'$:'$}发生了什么事在‘A’和‘C’下?+1,但结果和问题一样有点不同mine@dawg正如我所认为的,它被拒绝了
我想应该是这样的。我将问题的预期结果解释为暗示{'$','$'}是一个哨兵值,用于指示停止递归的位置,尽管在本例中它似乎不是严格必需的。@npdu是的,我现在看到了。在'a'和'C'下的子命令{'$':'$}发生了什么事?+1,但结果和问题有点不同mine@dawg它被拒绝了,我认为它应该被拒绝。我将问题的预期结果解释为暗示{'$','$'}是一个指示停止递归的位置的哨兵值,尽管在本例中它似乎不是严格必需的。@npdu是的,我现在看到了。