簡體   English   中英

如何通過在 python 中的分隔符上拆分鍵來從 dict 創建嵌套的 dict?

[英]How do I create a nested dict from a dict by splitting the keys on a delimiter in python?

我有一個像下面這樣的字典:

a = { 
  'customer_name': 'bob', 
  'customer_phone': '555-1212', 
  'order_0_number': 'A33432-24',
  'order_0_date': '12/12/12',
  'order_1_number': 'asd24222',
  'order_1_date': '12/14/12'
}

我需要它在下划線上拆分並放入這樣的嵌套字典中:

b = {
  'customer': {
    'name': 'bob',
    'phone': '555-1212'
  },
  'order': {
    '0': {
      'date': '12/12/12',
      'number': '...' },
    '1': { ... etc.

我擁有的實際數據比這更深層嵌套。 我已經很深入了,但是我一直在思考如何在 Python 中做到這一點:

def expand_data(field, value):

  split_field = field.split('_', 1)

  #base case, end of string
  if len(split_field) == 1:
    child_element[split_field[0] = value
    return child_element
  else:
    child_element[split_field[0]] = expand_data(split_field[1],value)
    return child_element

b = {}
for k,v in a.iteritems():
  b += expand_data(k, v) # stuck here because I can't add nested dicts together

但我不完全確定這是否是正確的方法。 我還沒有運行這段代碼,現在只是想考慮一下。

此外,dict 鍵將來可能會改變,所以我只能依賴“_”下划線在那里拆分。 我也不知道它需要嵌套多深。

通用解決方案:

def nest_dict(flat_dict, sep='_'):
    """Return nested dict by splitting the keys on a delimiter.

    >>> from pprint import pprint
    >>> pprint(nest_dict({'title': 'foo', 'author_name': 'stretch',
    ... 'author_zipcode': '06901'}))
    {'author': {'name': 'stretch', 'zipcode': '06901'}, 'title': 'foo'}
    """
    tree = {}
    for key, val in flat_dict.items():
        t = tree
        prev = None
        for part in key.split(sep):
            if prev is not None:
                t = t.setdefault(prev, {})
            prev = part
        else:
            t.setdefault(prev, val)
    return tree


if __name__ == '__main__':
    import doctest
    doctest.testmod()

這是您可以使用的步驟,但由於您沒有向我們展示您的任何代碼,因此我不會提供代碼。

  1. 處理您的鑰匙,您可以輕松地for key in yourDico使用for key in yourDico
  2. 然后,檢測您的模式customerorder以拆分值以獲得所需的值。
  3. 考慮到您從第一個拆分中得到的內容,請使用新數據創建dico,並在拆分中仍包含_重復拆分,這似乎是您的拆分字符。
b = {}
b["customer"] = {"name": a["customer_name"], "phone": a["customer_phone"]}
for key in a.keys():
    if key.startswith("order_"):
        o, i, f = key.split("_")
        order = b.get("order", {})
        order_i = order.get(i, {})
        order_i[f] = a[key]
        b["order"] = order
        b["order"][i] = order_i

print(b)

輸出:

{'customer': {'name': 'bob', 'phone': '555-1212'},
 'order': {'0': {'date': '12/12/12', 'number': 'A33432-24'},
           '1': {'date': '12/14/12', 'number': 'asd24222'}}}

另一個帶有一些評論的通用解決方案:

def expand_flatdict_to_tree(dict, sep = '_', to_lower = True):
    tree = {}
    
    for src, val in dict.items():
        ref = tree

        if to_lower:
            src = src.lower()
    
        for i, part in enumerate(src.split(sep)):
            if part not in ref:
                ref[part] = {}
            if i == len(src.split(sep)) -1:
                ref[part] = val # we cannot do ref = val after loop, as assignment to the ref itself will be passed by assignment
                break
            ref = ref[part] # update nest reference
    
    return tree


flat_dict = {
    'LOGLEVEL': 'INFO',
    'DB_ENABLED': True,
    'DB_CONNECTOR_HOST': 'localhost',
    'DB_CONNECTOR_USER': 'root',
}

print (expand_flatdict_to_tree(flat_dict))

# {
#     'loglevel': 'INFO',
#     'db': {
#         'enabled': True,
#         'connector': {
#             'host': 'localhost',
#             'user': 'root'
#         }
#     }
# }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM