将字典树转换为多维列表

时间:2014-01-11 15:47:54

标签: python dictionary multidimensional-array

我有这样的词典(Python):

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

如何将其转换为像这样的多维数组?:

['G', 
      ['G', 
          ['T', ['A'],
           'C']
       ], 
  'C', ['G'] 
]

谢谢

2 个答案:

答案 0 :(得分:2)

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']]]]

答案 1 :(得分:2)

首先,我假设您不关心词典中键的顺序,因为词典是无序的。如果您确实关心,那么除非您切换到使用collections.OrderedDict或同等效果,否则没有任何解决方案能够满足您的需求。

其次,虽然您现在使用字符串'end'作为您的标记值来指示处理应该停止的位置,但是没有迹象表明我们应该对任何价值不是字典。可以修改代码以适应其他类型的递归,但是现在我们将它保持这么简单,并且只是跳过树中的所有非字典值(尽管我们处理它们的键)。

有了这些假设,我会用一对递归函数做到这一点。在这一个中,编写了transform,以便您可以根据需要将此类模式与其他转换函数一起使用。 transform的操作比列表理解要复杂一点,因为我们将结果列表拼接到输出列表中 - 从某种意义上讲,"展平"输出略有。

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';相应地更新代码。