2016-02-19 101 views
1

我正在解析一個json - >dict具有嵌套在任意深度值的對象。例如,外層是字段(數據來自客戶服務售票系統),例如'name','sprint_team'等等。但是對於某些字段,它們有嵌套的dict,它們將具有像' id','value'等...如何處理任意嵌套深度的字典屬性?

我把它放在一個平面文件中,然後複製到AWS Redshift,但我試圖找出一種有效的方法來處理所有我可能需要的值的不同嵌套級別。我想用一個查找表,如:

lookup = { 
'customfield_12700': ('sprint_team', 'name'), 
'customfield_13208': ('department', 'sub_department', 'name') 
} 

其中value[0]總是查找名稱,然後可以有額外參數,這將是我的嵌套層次的n個。我首先使用查找表的原因是因爲Jira使用自定義字段,我需要將它們映射到我們的雲數據庫中的列名稱。例如,在sprint_team字段上,我需要我的平面文件的name屬性等...

如何創建一個函數,該函數將採用字典對象,然後使用查找表來返回我需要的值,不管它的嵌套程度如何?

+0

你在找這樣的事嗎? http://stackoverflow.com/questions/10756427/loop-through-all-nested-dictionary-values – idjaw

+1

遞歸是我的第一個想法,但我通常回避在將用於生產的代碼中使用遞歸。 – flybonzai

+0

如果你有一個遞歸結構需要被平滑,那麼沒有理由迴避遞歸解析。這不是實現目標的最佳方式,它是**正確的方式**來實現這些目標。由於您的問題*需要*將分層數據移動到標準RDBM,因此在存儲之前應該考慮正確地對輸入進行標準化。 – msw

回答

2

是這樣的?

這使用你的查找表的想法,並且一次只能在一個級別上向下瀏覽字典。

>>> data = {"foo": {"bar": {"baz": 1}}} 
>>> lookup = { 
... 'customfield': ("foo", "bar", "baz") 
... } 

>>> def nest(data, name): 
... path = lookup[name] 
... d = data 
... for p in path: 
...  d = d[p] 
... return d 
... 
>>> nest(data, 'customfield') 
1 

這也可以完成遞歸,這應該是罰款,除非你的類型的字典是非常深度嵌套!

def nest(data, path): 
     if len(path) == 0: 
      return data 
     else: 
      return nest(data[path[0]], path[1:]) 

def find(data, name): 
    return nest(data, lookup[name]) 

>>>find(data, 'customfield') 
1 

或者,在使用一個時髦的功能方法:

>>> from operator import itemgetter 
>>> from functools import reduce 
>>> def compose(*functions): 
...  return reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x) 

>>> nest = compose(*[itemgetter(name) for name in reversed(lookup['customfield'])]) 
>>> nest(data) 
1 

itemgetter提供訪問具有指定名稱的屬性的功能。 compose將這些函數組合在一起以生成提取嵌套數據的單個函數。

您也可以預先生成這些函數並將它們存儲在lookup而不是路徑中,因此可以在需要時直接使用它們。

(我們必須定義我們自己的compose函數,因爲Python沒有內置函數)。