"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

ネストした辞書の初期化・更新・一覧・JSON保存をまとめておく/Python3(備忘)

pythonの辞書型は、ネストできるので、非常に便利です。

でも、ネストした辞書の扱い方は、ちょっとしていないと度忘れしがちなので、ちょっとまとめておきます。

f:id:arakan_no_boku:20190427205325j:plain

 

ネストした辞書の事例

 

例えば、「A,B,C,Dの4つのテキストデータに登場する単語の割合をそれぞれ保持する」みたいなことをする場合です。 

ネストさせないで普通にやろうとすると、以下のような感じ。

A_dic['単語'] = 0.035

B_dic['単語'] = 0.236

C_dic['単語'] = 0.432

D_dic['単語'] = 0.065

わかりやすいですけど、4つの辞書にわかれてしまうのが、ちょっと嫌です。

pythonだと、これをネストさせて一つの辞書に収めることができます。

word_dic['単語']['A']  = 0.035

word_dic['単語']['B']  = 0.236

word_dic['単語']['C']  = 0.432

word_dic['単語']['D']  = 0.065

 これが何かと使い勝手が良いのです。 

 

 

初期化のやり方

 

こういうように2段にネストした辞書の初期化です。

{'幸せ':

  {'pcount': 0, 'ncount': 0, 'prate': 0, 'nrate': 0}

}

 2通りのやり方があります。

 

その1 

 

setdefault()を使うスタンダードな方法です。

keyA = 'pcount'
keyB = 'ncount'
keyC = 'prate'
keyD = 'nrate'
word = '幸せ'

word_dic = {}
word_dic.setdefault(word,{})
word_dic[word].setdefault(keyA,0)
word_dic[word].setdefault(keyB,0)
word_dic[word].setdefault(keyC,0)
word_dic[word].setdefault(keyD,0)

 

その2 

 

__missing__を実装した拡張dictクラスを作る方法です。

class MyDict(dict):
def __missing__(self,key):
    v = self[key] = type(self)()
    return v

 

例えば、上記のようにクラスを作っておくわけです。 

そすすると、以下のように初期化できるようになります。

w_dic = MyDict()
w_dic[word]
w_dic[word][keyA] = 0
w_dic[word][keyB] = 0
w_dic[word][keyC] = 0
w_dic[word][keyD] = 0
 

自分は、「その1」のsetdefaultを使うやり方の方が馴染んでいるので、使う頻度は多いです・・けど、3段4段と複雑なネストになると「その2」のやり方でないと、ソースがグチャグチャするかなとは思います。

 

辞書の全件を処理する

 

ネストした辞書をforループでまわすときは、再帰で処理してやる必要があります。 

とりあえず、全部の要素を書き出す処理はこんな感じで、関数にして、インスタンスを調べて辞書だったら、再帰呼出しです。

def recursive_dict(argd):
    for k in sorted(argd.keys(),reverse=False):
        if(isinstance(argd[k],dict)):
            recursive_dict(argd[k])
        else:
            print("key is {0}/value is{1}".format(k,argd[k]))

 

この出力はこんな感じになります。

key is ncount/value is0.7332
key is nrate/value is0.4568
key is pcount/value is20
key is prate/value is12
key is ncount/value is0
key is nrate/value is0
key is pcount/value is0
key is prate/value is0

 

JSON形式でファイルに保存する

 

ネストした辞書は、JSON形式で保存しておくと、復元も超簡単です。 

まず、保存します。

import json
fw = open('test.json','w')
json_data = json.dump(w_dic,fw,indent=4)
fw.close()

 

これだけで、test.jsonというファイルがカレントフォルダにできます。 

こんどは、保存したファイルから辞書を復元します。

fr = open('test.json','r')
r_dic = json.load(fr)
fr.close()

 

これでr_dicに、辞書が復元できてます。

{'幸せ': {'pcount': 20, 'ncount': 0.7332, 'prate': 12, 'nrate': 0.4568}, '当たり前': {'pcount': 20, 'ncount': 0.7332, 'prate': 12, 'nrate': 0.4568}} 

 これくらいできれば、ネストした辞書を使って、普通のことならできますね。

ではでは。