2012-09-12 162 views
1

我列出的元組的嵌套列表看起來像這樣(元組等):Python:將列表元組的嵌套列表轉換爲字典?

[(' person', 
[(('surname', u'Doe', True),), 
(('name', u'John', False),), 
('contact', 
[(('email', u'[email protected]', True),), 
(('phone', u'', False),), 
(('fax', u'+0987654321', False),)]), 
('connection', 
[(('company', u'ibcn', True),), 
('contact', 
[(('email', u'[email protected]', True),), 
(('address', u'main street 0', False),), 
(('city', u'pythonville', False),), 
(('fax', u'+0987654321', False),)])])])] 

因爲誰也不知道名單也不怎麼深內的(雙)元組既不數量的方式嵌套走。

我想將其轉換爲一個嵌套的詞典(詞典),消除了布爾值,像這樣:

{'person': {'name': 'John', 'surname': 'Doe', 
    'contact': {'phone': '', 'email': '[email protected]','fax': '+0987654321', 
    'connection': {'company name': 'ibcn', 'contact':{'phone': '+2345678901', 
        'email': '[email protected]', 'address': 'main street 0' 
        'city': 'pythonville', 'fax': +0987654321' 
}}}}} 

所有我有,到目前爲止,是可以打印嵌套結構的遞歸方法在每行的方式:

def tuple2dict(_tuple): 
    for item in _tuple: 
     if type(item) == StringType or type(item) == UnicodeType: 
      print item 
     elif type(item) == BooleanType: 
      pass 
     else: 
      tuple2dict(item) 

,但是,我不知道我是在正確的軌道上......

編輯: 我已經編輯了原來的結構,因爲它錯過了一個逗號。

+1

你的元組壞了... –

+0

你說得對,我修好了。 – katamayros

+0

nope仍然打破......你錯過了一個逗號,我假設 –

回答

3

您正處在正確的軌道上。遞歸方法將起作用。據我可以從您的示例數據告訴,每個元組第一個有字符串項,包含密鑰。之後,您可以有另一個元組或列表作爲值,或者是一個字符串值,後跟一個布爾值true或false。

編輯:

遞歸的訣竅是,你必須知道什麼時候停止。基本上,在你的情況下,似乎最深的結構是嵌套的三元組,匹配名稱和值。

黑客入侵了一下。我可恥地承認這是世界上最醜陋的代碼。

def tuple2dict(data): 
    d = {} 
    for item in data: 
     if len(item) == 1 and isinstance(item, tuple): 
      # remove the nested structure, you may need a loop here 
      item = item[0] 
      key = item[0] 
      value = item[1] 
      d[key] = value 
      continue 
     key = item[0] 
     value = item[1] 
     if hasattr(value, '__getitem__'): 
      value = tuple2dict(value) 
     d[key] = value 
    return d 
+0

是的,沒錯。我花了很多時間試圖找到一個解決方案,但迄今爲止還沒有能力。我不確定遞歸步驟中的聲明是什麼。我嘗試了很多,但都沒有工作。 – katamayros

+0

謝謝,這很好用!當我完成後,我會發布最終版本的代碼。我不能投票給你的答案,因爲我對stackoverflow很新穎:-(當我得到15分以上時會這樣做。 – katamayros

+0

地雷醜陋的:P –

0

你絕對是在正確的軌道上。遞歸函數是要走的路。

一個字典可以通過給出長度爲2的元組來迭代構建。 現在,爲了擺脫布爾值,可以使用切片。除了前兩個元素之外,切除所有的東西。

>> (1,2,3)[:3] 
(1,2) 
1

不漂亮......但它的作品...基本上

def t2d(t): 
if isinstance(t,basestring):return t 
length = len(t) 
if length == 1: 
    return t2d(t[0]) 
if length == 2: 

    t1,t2 = t2d(t[0]),t2d(t[1]) 
    print "T:",t1,t2 
    if isinstance(t1,dict) and len(t1) == 1: 
     t2['name'] = t1.values()[0] 
     t1 = t1.keys()[0] 
    return dict([[t1,t2]]) 
if length == 3 and isinstance(t[2],bool): 
    return t2d(t[:2]) 

L1 =[t2d(tp) for tp in t] 
L2 = [lx.items() for lx in L1] 
L3 = dict([i[0] for i in L2]) 
return L3 

我應該提到它與您發佈的字典工作的具體......(好像公司wasnt相當設置正確,所以我(見t2 ['name'] ...))

+0

謝謝,我看到你們都使用「isinstance」而不是「type」,它更好嗎? – katamayros

+0

是的,因爲它會匹配繼承類,所以basestring匹配字符串和unicode –

+0

好吧,有道理......謝謝! – katamayros

0

這是我的最終解決方案。不是很優雅,我必須承認。 它還通過將鍵與現有鍵連接來處理鍵的多個條目。

def tuple2dict(_obj): 
    _dict = {} 
    for item in _obj: 
     if isinstance(item, tuple) or isinstance(item, list): 
      if isinstance(item[0], basestring): 
       _dict[item[0]] = tuple2dict(item[1]) 
      else: 
       if isinstance(item[0], tuple): 
        # if the key already exists, then concatenate the old 
        # value with the new one, adding a space in between. 
        _key = item[0][0] 
        if _key in _dict: 
         _dict[_key] = " ".join([_dict[_key], item[0][1]]) 
        else: 
         _dict[_key] = item[0][1] 
    return _dict