1

序章

次の辞書には、3 つのレベルのキーと値があります。

d = {
    1:{
        'A':{
            'i': 100,
            'ii': 200
            }, 
        'B':{
            'i': 300
            }
        }, 
    2:{
        'A':{
            'ii': 500
            }
        }
    }

追加する必要がある例。

d[1]['B']['ii'] = 600      # OK
d[2]['C']['iii'] = 700     # Keyerror on 'C'
d[3]['D']['iv'] = 800      # Keyerror on 3

問題文

必要なネストされたキーを作成し、キー エラーを回避するコードを作成したかったのです。

解決策 1

私が思いついた最初の解決策は次のとおりです。

def NewEntry_1(d, lv1, lv2, lv3, value):
    if lv1 in d:
        if lv2 in d:
            d[lv1][lv2][lv3] = value
        else:
            d[lv1][lv2] = {lv3: value}
    else:
        d[lv1] = {lv2: {lv3: value}}

正当に思えますが、これをコードの一部に順番に埋め込むと、気が遠くなります。私は他のソリューションについて Stackoverflow を調査し、get() および setdefault() 関数を読んでいました。

解決策 2

get() と setdefault() についてはたくさんの資料がありますが、ネストされた辞書についてはそれほど多くはありません。最終的に私は思いつくことができました:

def NewEntry_2(d, lv1, lv2, lv3, value):
    return d.setdefault(lv1, {}).setdefault(lv2,{}).setdefault(lv3, value)

これは 1 行のコードなので、実際に関数にする必要はありません。操作を含めるように簡単に変更可能:

d[lv1][lv2][lv3] = d.setdefault(lv1, {}).setdefault(lv2,{}).setdefault(lv3, 0) + value

完璧に見えますか?

質問

大量のエントリを追加し、多くの変更を行う場合、オプション 2 はオプション 1 より優れていますか? または、関数 1 を定義して呼び出す必要がありますか? 私が探している答えは、速度やエラーの可能性を考慮に入れる必要があります。

NewEntry_1(d, 1, 'B', 'ii', 600)
# output = {1: {'A': {'i': 100, 'ii': 200}, 'B': {'i': 300, 'ii': 600}}, 2: {'A': {'ii': 500}}}

NewEntry_1(d, 2, 'C', 'iii', 700)
# output = {1: {'A': {'i': 100, 'ii': 200}, 'B': {'i': 300, 'ii': 600}}, 2: {'A': {'ii': 500}, 'C': {'iii': 700}}}

NewEntry_1(d, 3, 'D', 'iv', 800)
# output = {1: {'A': {'i': 100, 'ii': 200}, 'B': {'i': 300, 'ii': 600}}, 2: {'A': {'ii': 500}, 'C': {'iii': 700}}, 3: {'D': {'iv': 800}}}

その他の背景

私は、非常に具体的な分析に役立つグラフ DB を作成するために Python を使用することを検討しているビジネス アナリストです。ディクショナリ構造は、1 つのノードが隣接するノードの 1 つに与える影響を説明するために使用されます。

  • lv1 は Node From です
  • lv2 は Node To
  • lv3はイテレーション
  • 値は影響力 (%)

最初の反復では、ノード 1 はノード 2 に直接影響を与えます。2 番目の反復では、ノード 1 は、ノード 2 が影響を与えているすべてのノードに影響を与えます。

私はそれに役立つパッケージ (networkx) を知っていますが、それらを使い始める前に Python/GraphDB を理解しようとしています。

4

1 に答える 1

5

ネストされた辞書については、 をご覧くださいdefaultdict。これを使用すると、関数呼び出しのオーバーヘッドを大幅に節約できます。ネストされたdefaultdict構造lambdaは、デフォルト ファクトリの関数に頼っています。

d = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))  # new, shiny, empty
d[1]['B']['ii'] = 600      # OK
d[2]['C']['iii'] = 700     # OK
d[3]['D']['iv'] = 800      # OK

更新:深くネストされたを作成するために知っておくと便利なトリックdefaultdictは次のとおりです。

def tree():
    return defaultdict(tree)

d = tree()  
# now any depth is possible
# d[1][2][3][4][5][6][7][8] = 9
于 2016-04-29T17:57:46.053 に答える