2016-11-21 7 views
0

私はPythonユーティリティを開発しています。これの一部はファイルのインデックスを生成することです
深さを知らずに多次元辞書に動的にアクセスすることは可能ですか?私は例のデータを持っていた場合
はすなわち:
example = {'main': {'2': {'2': '2-2', '1': '2-1'}, '1': {'2': '1-2', '1': '1-1'}}}
は私が example["main","2","1"]に似た何かを要素にアクセスすることができ、それが2-1を返す方法はありますか? 自分のダイビングアルゴリズムを書くことができますが、私の経験では値に書き込むことができないことがわかりました。
["key"、 "key2"]でPython辞書にアクセスする

+0

をあなたは「その値に書き込むことができない」とはどういう意味ですか? –

+0

あなたはいつでも 'example ['main'] ['2'] ['1']'を実行できます。もちろん、キー( 'main'、 '2'、 '1')を知っている必要があります – lucasnadalutti

+0

なぜexample ["main"、 "2"、 "1"] ' main "] [" 2 "] [" 1 "]'? – thorhunter

答えて

0

あなたが本当にそうする必要がある場合は、独自のdictクラスをロールする必要があります。幸いにもあなたは__getitem__からdictまですべてを継承することができます。特別にコード化されていない限り

class MyDict(dict): 
    def __getitem__(self, keys): 
     if isinstance(keys, str): 
      # this special-case saves you if you try to do normal indexing 
      # on a string. 
      return super().__getitem__(keys) 
     cur = self 
     for key in keys: 
      cur = cur.get(key, {}) 
      # the default option here returns an empty dict instead 
      # of raising a KeyError. That might not be what you want 
     return cur 

これはタプルのキーにあなたの能力を削除することに注意してください、そう{("some", "tuple", "values"): "any value"}のようなキー/ヴァルスはアクセスできなくなります。それは...のように見えるかもしれません。

次に、この新しいdictにマッピングをキャストし、その方法で検索できます。

example = {'main': {'2': {'2': '2-2', '1': '2-1'}, '1': {'2': '1-2', '1': '1-1'}}} 
result = MyDict2(example)['2', '2', '1'] 

また__setitem__を継承する場合には、同様に、このことにより、値を設定する必要が言及。

class MyDict(dict): 
    def __getitem__(self, keys): 
     # as above 
    def __setitem__(self, keys, value): 
     if isinstance(keys, str): 
      super().__setitem__(keys, value) 
     cur = self 
     for key in keys[:-1]: 
      cur = cur.setdefault(key, {}) 
     cur[keys[-1]] = value 
+1

彼はこれらのネストされたdict値への代入について言及していますので、 '__setitem __()'も追加したいかもしれません。 – Aaron

+0

@Aaronうーん、テストして実行可能になるまで削除しています。 –

+0

'super().__ setitem __(keys、value)'は 'super()を返すべきではありません。__setitem __(keys、value) 'を返すと、奇妙なエントリがロードされます。 –

0

あなたはこのように機能させることができます。使用方法の

def get_item(d, keys): 
    current = d 
    for k in keys: 
     current = current[k] # You can add some error handling here 
    return current 

例:https://repl.it/E49o/1

あなたが最後のインデックスで値を変更したい場合は、あなたがこのような何かを行うことができます。

def set_item(d, keys, new_value): 
    current = d 
    for k in keys[:-1]: # All the keys except the last one 
     current = current[k] 
    current[keys[-1]] = new_value 
+0

似たようなものを作成しました。問題はありません。同様の関数で値を設定します。 –

+0

私はセッターで自分の答えを変更しました。 – Arya

0

また例えば、派生dictのクラスで@Aryaによって提案されたアイデアをラップすることができます。:

class ListAccess(dict): 
    def __getitem__(self, item): 
     if type(item) in [tuple,list]: 
      item = list(item) 
      ret = self 
      while True: 
       try: 
        ret = ret[item.pop(0)] 
       except IndexError: 
        break 
      return ret 
     else: 
      return super(ListAccess, self).__getitem__(item) 

store = ListAccess({'main': {'2': {'2': '2-2', '1': '2-1'}, '1': {'2': '1-2', '1': '1-1'}}}) 
print store['main','2','1']