使用 yield 壓平多層巢狀字典列表混合資料
阿新 • • 發佈:2019-12-31
在上一篇文章裡面,我們講到了如何使用Python的yield
關鍵字簡化程式碼,壓平多層巢狀字典的。
那麼如果我們的資料不僅僅有字典,還有列表,是一個字典列表多層巢狀的資料怎麼辦呢?例如:
nest_dict = {
'a': 1,'b': {
'c': 2,'d': 3,'e': {'f': 4}
},'g': {'h': 5},'i': 6,'j': {'k': {'l': {'m': 8}}},'n': [1,{'o': 1,'p': [1,2,3],'q': {'r': {'s': 100}}},3,[1,5]
}
複製程式碼
現在,請停下來,敲一敲程式碼,想想如何把處理列表的邏輯新增進去。
首先,我們來看一下最終被壓平以後的資料長什麼樣:
{'a': 1,'b_c': 2,'b_d': 3,'b_e_f': 4,'g_h': 5,'j_k_l_m': 8,'n_0': 1,'n_1_o': 1,'n_1_p_0': 1,'n_1_p_1': 2,'n_1_p_2': 3,'n_1_q_r_s': 100,'n_2': 3,'n_3_0': 1,'n_3_1': 2,'n_3_2': 3,'n_4': 5}
複製程式碼
對於'n': ['a','b','c']
這種形式的資料,我們把它轉換為: {'n_0': 'a','n_1': 'b','n_2': 'c'}
我們原來的核心程式碼是這樣的:
def flat(x):
for key,value in x.items():
if isinstance(value,dict):
for k,v in flat(value):
k = f'{key}_{k}'
yield (k,v)
else:
yield (key,value)
複製程式碼
你的第一反應,是不是這樣修改程式碼:
def flat(x):
for key,v)
elif isinstance(value,list):
"一大堆處理列表的程式碼"
else:
yield (key,value)
複製程式碼
如果你使用return
和遞迴,你可能確實需要這樣寫。
但如果你使用yield
關鍵字,那麼,你雖然也要修改程式碼,可是修改的地方卻不是這裡。我們要修改的地方在for key,value in x.items()
。
因為.items()
這個方法是字典的方法,列表沒有這個方法。所以我們需要寫一個通用的迭代生成器,支援字典和列表,所以我們增加一個函式:iter_x
:
def iter_x(x):
if isinstance(x,dict):
for key,value in x.items():
yield (key,value)
elif isinstance(x,list):
for index,value in enumerate(x):
yield (index,value)
複製程式碼
現在,我們在原來的程式碼中呼叫這段個新的生成器函式:
def flat(x):
for key,value in iter_x(x):
if isinstance(value,(dict,list)):
for k,value)
複製程式碼
其中,isinstance(value,list))
,相當於isinstance(value,dict) or isinstance(value,list)
。
我們來看一下執行效果:
掌握yield
關鍵字,你的程式設計思路和想問題的方式會發生一個重大的轉變。