2016-12-01 34 views
0

作爲一名java開發人員,我需要一些提示如何在python 2中解決這個問題。我的python技能處於開始狀態。但現在的問題是:使用點分隔字符串轉換爲嵌套複雜字典

我們爲設備提供服務,設備以某種格式報告一些技術統計數據,我們無法更改。服務器使用python運行。 主要的報告是作爲字典來的,我們需要保存json的方式。從字典到json的轉換不是問題,但是轉換平面和用點分隔的鍵需要轉換。

也許一個例子可以顯示我想說的。這是來自設備的格式,將其命名爲:

{ 
    'Device.DeviceInfo.SoftwareVersion': 'ote-2.2.1', 
    'Device.GatewayInfo.ProductClass': 'OEM-TX23', 
    'Device.GatewayInfo.SerialNumber': 'A223142D1CC7', 

    'Device.Ethernet.Interface.1.MaxBitRate': 1000, 

    'Device.HomePlug.Interface.1.AssociatedDevice.1.RxPhyRate': 522, 
    'Device.HomePlug.Interface.1.AssociatedDevice.1.TxPhyRate': 706, 
    'Device.HomePlug.Interface.1.AssociatedDevice.1.Active': 1, 
    'Device.HomePlug.Interface.1.AssociatedDevice.1.MACAddress': 'af:49:79:e4:64:fc', 

    'Device.HomePlug.Interface.1.AssociatedDevice.2.RxPhyRate': 544, 
    'Device.HomePlug.Interface.1.AssociatedDevice.2.TxPhyRate': 0, 
    'Device.HomePlug.Interface.1.AssociatedDevice.2.Active': 1, 
    'Device.HomePlug.Interface.1.AssociatedDevice.2.MACAddress': 'af:49:79:e4:64:dd', 


    'Device.Ethernet.Interface.2.MaxBitRate': 1000, 

    'Device.HomePlug.Interface.2.AssociatedDevice.1.RxPhyRate': 671, 
    'Device.HomePlug.Interface.2.AssociatedDevice.1.TxPhyRate': 607, 
    'Device.HomePlug.Interface.2.AssociatedDevice.1.Active': 1, 
    'Device.HomePlug.Interface.2.AssociatedDevice.1.MACAddress': 'bf:49:79:e4:64:fc', 

    'Device.HomePlug.Interface.2.AssociatedDevice.2.RxPhyRate': 340, 
    'Device.HomePlug.Interface.2.AssociatedDevice.2.TxPhyRate': 0, 
    'Device.HomePlug.Interface.2.AssociatedDevice.2.Active': 1, 
    'Device.HomePlug.Interface.2.AssociatedDevice.2.MACAddress': 'bf:49:79:e4:64:dd' 
} 

源中的整數值表示此接口的接口和AssociatedDevices的索引。所以整數後面的部分應該是多個詞典列表。結果中不應包含整數值

我們需要下面的嵌套結構,然後才能將其保存到數據庫,尤其是mysql文檔庫。再次,從嵌套字典到json的轉換不是問題。

這是我們需要的格式:

{ 
    'Device': { 
     'GatewayInfo': { 
      'SerialNumber': 'A223142D1CC7', 
      'ProductClass': 'OEM-TX23' 
     }, 
     'DeviceInfo': { 
      'SoftwareVersion': 'ote-2.2.1' 
     }, 
     'Ethernet': { 
      'Interface': [{ 
       'MaxBitRate': 1000 
      }, { 
       'MaxBitRate': 1000 
      }] 
     }, 
     'HomePlug': { 
      'Interface': [{ 
       'AssociatedDevice': [{ 
        'RxPhyRate': 522, 
        'TxPhyRate': 706, 
        'Active': 1, 
        'MACAddress': 'af:49:79:e4:64:fc', 
       }, { 
        'RxPhyRate': 544, 
        'TxPhyRate': 0, 
        'Active': 1, 
        'MACAddress': 'af:49:79:e4:64:dd', 
       }] 
      }, { 
       'AssociatedDevice': [{ 
        'RxPhyRate': 671, 
        'TxPhyRate': 607, 
        'Active': 1, 
        'MACAddress': 'bf:49:79:e4:64:fc', 
       }, { 
        'RxPhyRate': 340, 
        'TxPhyRate': 0, 
        'Active': 1, 
        'MACAddress': 'bf:49:79:e4:64:dd', 
       }] 
      }] 
     } 
    } 
} 

UPDATE: 第一個答案是部分正確的,只是整數後的部分應轉化成含有其餘的作爲字典的列表。

+0

並不多,遍歷列表並嘗試瞭解python中的不同數據結構。但我的問題是,python對我來說是新的。 – AdemC

回答

1

這應該工作。只是通過未轉換dictconvert,它會返回轉換dict

def convert(data): 
    to_convert = set() 
    new_dict = {} 
    for key, value in data.items(): 
     path_stack = [] 
     k_list = key.split('.') 
     temp_dict = new_dict 
     for k in k_list[:-1]: 
      path_stack.append(k) 
      if k.isnumeric(): 
       to_convert.add(tuple(path_stack)) 
      if k not in temp_dict: 
       temp_dict[k] = {} 
      temp_dict = temp_dict[k] 
     temp_dict[k_list[-1]] = value 

    for path in sorted(to_convert, key=len, reverse=True): 
     current_level = new_dict 
     for k in path[:-2]: 
      current_level = current_level[k] 
     if isinstance(current_level[path[-2]], dict): 
      new_level = [current_level[path[-2]][i] for i in sorted(current_level[path[-2]].keys())] 
     else: 
      new_level = current_level[path[-2]] 
     current_level[path[-2]] = new_level 

    return new_dict 
+0

感謝您解決問題。唯一需要改變的是,第10行中的「k.isnumeric」不適用於字符串,如果它不是unicode。 所以我改變了這一行 '嘗試: INT(K) to_convert.add(元組(path_stack)) 不同的是: pass' – AdemC

+0

很高興我能幫忙。 –

3

您可以遍歷原來的字典遞歸添加keys和增加價值的最後一項爲:

new_dict = {} 
for key, value in my_dict.items(): 
    k_list = key.split('.') 
    temp_dict = new_dict 
    for k in k_list[:-1]: 
     if k not in temp_dict: 
      temp_dict[k] = {} 
     temp_dict = temp_dict[k] 
    temp_dict[k_list[-1]] = value 

其中my_dict是在問題中提到你原來字典對象。通過new_dict

終值保持爲:

{ 
    "Device":{ 
     "GatewayInfo":{ 
     "SerialNumber":"A223142D1CC7", 
     "ProductClass":"OEM-TX23" 
     }, 
     "DeviceInfo":{ 
     "SoftwareVersion":"ote-2.2.1" 
     }, 
     "HomePlug":{ 
     "Interface":{ 
      "1":{ 
       "AssociatedDevice":{ 
        "1":{ 
        "RxPhyRate":522, 
        "Active":1, 
        "TxPhyRate":706, 
        "MACAddress":"af:49:79:e4:64:fc" 
        }, 
        "2":{ 
        "Active":1, 
        "MACAddress":"af:49:79:e4:64:dd", 
        "RxPhyRate":544, 
        "TxPhyRate":0 
        } 
       } 
      }, 
      "2":{ 
       "AssociatedDevice":{ 
        "1":{ 
        "RxPhyRate":671, 
        "Active":1, 
        "TxPhyRate":607, 
        "MACAddress":"bf:49:79:e4:64:fc" 
        }, 
        "2":{ 
        "RxPhyRate":340, 
        "MACAddress":"bf:49:79:e4:64:dd", 
        "TxPhyRate":0, 
        "Active":1 
        } 
       } 
      } 
     } 
     }, 
     "Ethernet":{ 
     "Interface":{ 
      "1":{ 
       "MaxBitRate":1000 
      }, 
      "2":{ 
       "MaxBitRate":1000 
      } 
     } 
     } 
    } 
} 
+0

看起來不錯,但在我的問題中提到。整數值如何?這些整數值不應該在最後一個字典中,這些值應該是數組開始的指示。 – AdemC

0

如果你想潛入你可能感興趣的模塊dotteddict蟒蛇。

這是一個有點棘手,但非常相互「pythonic」代碼。目前它不會將數字鍵轉換爲列表,但其中的一些概念絕對值得花費一段時間。