web-dev-qa-db-ja.com

Python 3:ネストされた辞書と辞書内のリストをフラット化する

複雑なネストされた辞書とリストのデータ構造を扱っています。データをフラット化し、ネストされたすべてのアイテムをレベル0にする必要があります。より明確にするために、以下の例を参照してください。

{a:1,b:2,c:{c1:[{c11:1,c12:2,c13:3},{c21:1,c22:2,c23:3}],d1:[{d11:1,d12:2,d13:3},{d21:1,d22:2,d23:3}]},x:1,y:2}

私はこれを平らにする必要があります:

{a:1,b:2,c_c1_c11:1, c_c1_c12:2,c_c1_c13:3,c_c1_c21:1,c_c1_c22:2,c_c1_c23:3, c_d1,d11:1...and so on}

この投稿 の最初の回答から参照しましたが、ネストされた辞書がある場合にのみ機能し、リストが辞書内にネストされ、さらに多くの辞書がそれらのリスト内にネストされている場合は機能しません。

ユースケースに合わせてコードを少し変更しましたが、このコードは機能しません

def flattenDict(d):
node_map = {}
node_path = []
def nodeRecursiveMap(d, node_path):
    for key, val in d.items():
        if ((type(val) is not dict)&(type(val) is not list)): 
            node_map['_'.join(node_path + [key])] = val
        if type(val) is list:
            def nodeListRecursion(val,node_path):
                for element in val:
                    if ((type(element) is not dict)&(type(element) is not list)) : node_map['_'.join(node_path + [key])] = element
                    if type(element) is list: nodeListRecursion(element,node_map)
                    if type(element) is dict: nodeRecursiveMap(element, node_path + [key])
            nodeListRecursion(val,node_path)
        if type(val) is dict: nodeRecursiveMap(val, node_path + [key])
nodeRecursiveMap(d, node_path)
return node_map

ここにコードを貼り付けると、インデントがめちゃくちゃになります。しかし、私はここでどんな助けでも本当に感謝します。

5
Ashish Kohli

あなたは物事を複雑にしすぎていると思います。キーと値を使用して、辞書から始めます。その値は、再帰したい辞書または辞書のリストのいずれかであるか、そうでない場合は、そのままにしておきます。そう:

def flatten(d):
    out = {}
    for key, val in d.items():
        if isinstance(val, dict):
            val = [val]
        if isinstance(val, list):
            for subdict in val:
                deeper = flatten(subdict).items()
                out.update({key + '_' + key2: val2 for key2, val2 in deeper})
        else:
            out[key] = val
    return out

私にくれます

In [34]: nested = {'a': 1, 'b': 2, 'c': {'c1': [{'c11': 1, 'c12': 2, 'c13': 3}, {'c21': 1, 'c22': 2, 'c23': 3}], 'd1': [{'d11': 1, 'd12': 2, 'd13': 3}, {'d21': 1, 'd22': 2, 'd23': 3}]}, 'x': 1, 'y': 2}

In [35]: flatten(nested)
Out[35]: 
{'a': 1,
 'b': 2,
 'c_c1_c11': 1,
 'c_c1_c12': 2,
 'c_c1_c13': 3,
 'c_c1_c21': 1,
 'c_c1_c22': 2,
 'c_c1_c23': 3,
 'c_d1_d11': 1,
 'c_d1_d12': 2,
 'c_d1_d13': 3,
 'c_d1_d21': 1,
 'c_d1_d22': 2,
 'c_d1_d23': 3,
 'x': 1,
 'y': 2}
6
DSM

私のプロジェクトでは、 DSMs answer から更新されたバージョンの関数を使用して、他のdictまたはdictのリストまたはリストを含む可能性のあるdictをフラット化します。お役に立てば幸いです。

def flatten(input_dict, separator='_', prefix=''):
    output_dict = {}
    for key, value in input_dict.items():
        if isinstance(value, dict) and value:
            deeper = flatten(value, separator, prefix+key+separator)
            output_dict.update({key2: val2 for key2, val2 in deeper.items()})
        Elif isinstance(value, list) and value:
            for index, sublist in enumerate(value, start=1):
                if isinstance(sublist, dict) and sublist:
                    deeper = flatten(sublist, separator, prefix+key+separator+str(index)+separator)
                    output_dict.update({key2: val2 for key2, val2 in deeper.items()})
                else:
                    output_dict[prefix+key+separator+str(index)] = value
        else:
            output_dict[prefix+key] = value
    return output_dict
0
Ali Hasan Imam