2

皆さん、

次のような他の辞書と配列のネストをいくつでも持つことができる任意の辞書があります。

{
    "a": {
        "b": "1",
        "c": [
            {
                "d": "2"
            },
            {
                "d": {
                    "e": "3",
                    "f": "4"
                }
            }
        ]
    }
}

これをツリーとしてうまく表現したいと思います。そのためには、次のような構造に変換したいと思います。

{
    "name": "a",
    "children": [
        {
            "name": "b",
            "value": "1"
        },
        {
            "name": "c",
            "children": [
                {
                    "name": "d",
                    "value": "2"
                },
                {
                    "name": "d",
                    "children": [
                        {
                            "name": "e",
                            "value": "3"
                        },
                        {
                            "name": "f",
                            "value": "4"
                        }
                    ]
                }
            ]
        }
    ]
}

そのためには、サブ辞書とサブ配列を同様に扱う必要があると思います。しかし、私はこの変換を行うためのアプローチを考え出すのに非常に苦労しています. 再帰を使用しようとしましたが、「名前」、「値」、および「子」のキー/値を含むノード クラスを使用しようとしましたが、恣意的に深い入力を解析するのに苦労していますこの通常のノード/ツリー表現を作成します。

これは、人々が以前に行ったことがあるように見えますか? ご意見をお待ちしております。

4

1 に答える 1

4

これをツリーのようなデータ構造として正しく識別しました。元の表現が明確かつ完全に壊れているため、これを変換することをお勧めします。

ツリーがあることがわかったので、そのノードが何であるかを自問する必要があります。あなたの場合、ノードは次のいずれかです。

  1. 名前と値を持つ葉
  2. 名前と子を持つ内部ノード

問題は、2番目のタイプの2つの異なる表現があることです。

  1. ペア("<name>", { "<child1>" : ..., "<child2>" })
  2. ペア("<name>", [{"<child1>" : ... }, { "<child2>": ... }])

あなたの例はそれを示していませんが、おそらく次のことも可能です:

("<name>", [{"<child1>" : ... }, { "<child2>": ..., "<child3>": ... }])

再帰は確かにこれを解決するための良い方法です。エッジケースは明確です、それはリーフノードです。最初に他の2つのケースを確認する必要があります。

def transform_node(name, val):
    if isinstance(val, list):
        val = ("children", [transform_node(k,v) for x in val for k, v in x.items()])
    elif isinstance(val, dict):
        val = ("children", [transform_node(*kv) for kv in val.items()])
    else:
        val = ("value", val)
    return dict([("name", name), val])

今、あなたは得る:

>>> transform_node("a", 3)
{'name': 'a', 'value': 3}
>>> transform_node("a", { "c1" : 3, "c2" : 4 })
{'name': 'a', 'children': [{'name': 'c2', 'value': 4}, {'name': 'c1', 'value': 3}]}
>>> transform_node("a", [{ "c1" : 3 }, { "c2" : 4, "c3": 5 }])
{'name': 'a', 'children': [{'name': 'c1', 'value': 3}, {'name': 'c3', 'value': 5}, {'name': 'c2', 'value': 4}]}

完全!今、あなたはただすることができます:

>>> tree = { "a": { "b": 1 }}
>>> transform_node("root", tree)
{'name': 'root', 'children': [{'name': 'a', 'children': [{'name': 'b', 'value': 1}]}]}

もちろん、「a」をルートにしたい場合は、ルートの最初の子を抽出するだけです。

とは言うものの、完全に型指定されていない辞書ではなく、クラスを使用してこれを実際のデータ型として表す方がおそらく良いでしょう。

于 2013-02-06T16:51:49.557 に答える