2016-03-22 18 views
3

ネストされた辞書と重複するキーでデータ構造を作成したいと思います。詳細な例は以下のとおりです。Pythonで重複するキーでネストされた辞書を作成する方法

data['State1']['Landon']['abc Area'] = 'BOB' 
data['State1']['Landon']['abc Area'] = 'SAM' 
data['State1']['Landon']['xyz Area'] = 'John' 
data['State2']['New York']['hjk Area'] = 'Ricky' 

for z in data['State1'].keys() , 
# I should get list ['Landon', 'Landon', 'Landon'] 
for y in data['State1']['Landon'].keys() , 
# I should get list ['abc Area', 'abc Area', 'xyz Area'] 

現在のデータを保存するために私が使用している余分なカウンター市/エリアの総エントリ(重複同様)を解析している間、私はネストされた使用する必要が

data = Autovivification() 
data[state][city][area][counter] = ID 

しかし、キーカウンターキーまでループします。ネストされた辞書用

for city in data['State1'].keys(): 
    for area in data['State1'][city].keys(): 
    for counter in data['State1'][city][area].keys(): 
    for temp in data['State1'][city][area][counter].values(): 
     cityList.append(city) 
     areaList.append(area) 

、私はnosklo

class AutoVivification(dict): 
    """Implementation of perl's autovivification feature.""" 
    def __getitem__(self, item):     
     try: 
      return dict.__getitem__(self, item) 
     except KeyError: 
      value = self[item] = type(self)() 
      return value 

によって投稿次のコードを発見し、重複キーを持つ辞書のために、私はコードがAutovivificationをマージする方法Scorpil

class Dictlist(dict): 
    def __setitem__(self, key, value): 
     try: 
      self[key] 
     except KeyError: 
      super(Dictlist, self).__setitem__(key, []) 
     self[key].append(value) 

により投稿されました重複したクラスコード?またはそのようなシナリオを処理するための他のpythonic方法はありますか?

Data['State']['City']['Area'] = [] 
Data['State']['City']['Area'].append(ID) 
+2

あなたは説明できます、なぜあなたが重複キーが必要なのでしょうか? 'エリア'が複数のIDを追加できるリストになっても問題ありませんか? –

+0

@germn:私は詳細な説明で質問を編集しました。 – Aniketan

+0

をチェックしてください。あなたが与えられたデータに必要なリストを返す新しい 'items_in'関数を追加しました。 dict/list構造を扱う関数を実装するのが簡単で分かりやすく、新しい構造を実装しようとしているでしょう。 –

答えて

3

もう一つの例defaultdictを使用して:

from collections import defaultdict 


data = defaultdict( # State 
    lambda: defaultdict( # City 
     lambda: defaultdict(list) # Area 
    ) 
) 


data['State']['City']['Area'].append('area 1') 
data['State']['City']['Area'].append('area 2') 
data['State']['City']['Area'].append('area 2') 


areas = data['State']['City']['Area'] 
print(areas) # ['area 1', 'area 2', 'area 2'] 

total = len(areas) 
print(total) # 3 

このソリューションを使用して、必要な項目のリストを取得する方法:

data['State1']['Landon']['abc Area'].append('BOB') 
data['State1']['Landon']['abc Area'].append('SAM') 
data['State1']['Landon']['xyz Area'].append('John') 
data['State2']['New York']['hjk Area'].append('Ricky') 


def items_in(d): 
    res = [] 
    if isinstance(d, list): 
     res.extend(d) 
    elif isinstance(d, dict): 
     for k, v in d.items(): 
      res.extend([k] * len(items_in(v))) 
    else: 
     raise ValueError('Unknown data') 
    return res 


print(items_in(data['State1'])) # ['Landon', 'Landon', 'Landon'] 
print(items_in(data['State1']['Landon'])) # ['xyz Area', 'abc Area', 'abc Area'] 
print(items_in(data['State1']['Landon']['abc Area'])) # ['BOB', 'SAM'] 
print(items_in(data['State1']['Landon']['xyz Area'])) # ['John'] 

print(items_in(data['State2'])) # ['New York'] 
print(items_in(data['State2']['New York'])) # ['hjk Area'] 
1

一つの簡単な方法は、それリスト作成し、その後、単にリストにすべての新しいキーを追加することです

class AutoVivificationDL(Dictlist): 
    """Implementation of perl's autovivification feature.""" 
    def __getitem__(self, item):     
     try: 
      return dict.__getitem__(self, item) 
     except KeyError: 
      value = self[item] = type(self)() 
      return value 
0

あなたが代わりにdictsの自動vivificates Dictlists 1でAutoVivicationクラスを置き換えることができます::

+0

ありがとう、私はより多くの説明で質問を編集した、あなたは確認してくださいできますか? 、あなたのコード 'RuntimeError:Pythonオブジェクトの呼び出し中に最大再帰深度を超過しました'を使用したときに発生します。 – Aniketan

+0

ええ、それは考えていませんでした。私は、これはPythonがこの全体のAutoVivificationの事はPython的ではないことを伝える:)あなたはdefaultdict'、代わりに「重複したエントリ」の定期的なリスト 'の組み合わせを使用して、おそらく方がいいでしょうと思います。まだそうしていない場合は、そのような超柔軟なデータ構造が必要かどうか、またはあらかじめ決められた深さのネストされたdictを作成するために十分なデータを事前に知っているかどうか再考しようとするかもしれません。 – egpbos

0
Data = {} 


values = [ 
    dict(State="CA", City="San Francisco", Area="North", Id="customer1"), 
    dict(State="CA", City="San Francisco", Area="Embarcadero", Id="customer1"), 
    dict(State="CA", City="San Francisco", Area="North", Id="customer2"), 

] 

for v in values: 
    #grab the existing entry. if it doesn't exist, returns a list 
    li = Data.setdefault((v["State"],v["City"],v["Area"]),[]) 
    li.append(v["Id"]) 

print "Data:%s" % (Data) 

出力:

Data:{('CA', 'San Francisco', 'North'): ['customer1', 'customer2'], ('CA', 'San Francisco', 'Embarcadero'): ['customer1']} 

あなたは非常に単純なId値に限定されません。あなたが望むものをリストに追加することができます。いくつかの場所でこれを行う予定の場合は、https://docs.python.org/2/library/collections.html#collections.defaultdictを参照してください。これは、組み込みのデフォルトを指定します。

実際、リストではなく辞書にIDを追加することもできます。すべて同じです。

関連する問題