簡體   English   中英

將列表轉換為字典,其中每個鍵都嵌套在下一個鍵下

[英]Convert a list into a dict where each key is nested under the next one

我想轉換這個列表:

[1,2,3,4,5]

進入這個字典:

{ 1 :
  { 2 :
    { 3 :
      { 4 : 5 }}}}

這聽起來並不太復雜,但是當需要為比表面更深的鍵分配值時,我感到很困惑。 我有一個遞歸函數來查找我的字典有多深,但我不知道如何告訴我的算法“在此處添加新鍵”。

您正在尋找一個遞歸函數,該函數構建一個字典,其中第一個列表元素作為鍵,列表的其余部分作為值進行轉換:

l = [1, 2, 3, 4, 5]

def l2d(l):  
    if len(l) < 2: # Not good
        raise Exception("The list is too short")
    if len(l) == 2: # Base case
        return {l[0]: l[1]}
    # Recursive case
    return {l[0]: l2d(l[1:])}

l2d(l)
# {1: {2: {3: {4: 5}}}}

另一個有趣的方法是使用functools.reduce

from functools import reduce
reduce(lambda tail,head: {head: tail}, reversed(l))
# {1: {2: {3: {4: 5}}}}

它逐步將字典構造函數應用於列表的第一個元素和其余元素。 列表先倒序,所以構造自然從最后開始。 如果列表太短,函數會返回它的第一個元素,這可能是也可能不是。

“減少”解決方案要快得多,大約兩個數量級。 底線:避免遞歸

不需要遞歸來解決這個問題。 一個簡單的循環就足夠了。

def nest(keys):
    if not keys:
        return {}
    elif len(keys) == 1:
        return key[0]
    root = level = {}
    for key in keys[:-1]:
        level[key] = {}
        level = level[key]
    level[key] = keys[-1]
    return root

或者,您可以從內到外構建 dict:

def nest(keys):
    if not keys:
        return {}
    current = keys[-1]
    for key in keys[-2::-1]:  # iterate keys in reverse
        current = {key: current}
    return current

這是使用遞歸邏輯直到列表長度為 1 的好方法。例如:

更新:修復空列表錯誤。

A = [1, 2, 3, 4, 5]

def rec_dict(listA):
    try:
        if len(listA) <= 1:
            listA = listA[0]
        else:
            listA = {listA.pop(0): rec_dict(listA)}
    except IndexError:
        pass
    return listA


print(rec_dict(A))

返回:

{1: {2: {3: {4: 5}}}}

我想使用不同的方法提出另一種選擇:

雖然不推薦使用ast.literal_eval ,但我認為在這種情況下可能會有用。 此外,您可以使用re.sub() + re.findall()幫助自己找到匹配項並正確進行替換。 這里的想法是使用列表的字符串表示。

import ast
import re

lst = [1, 2, 3, 4, 5]
lst_str = str(lst).replace("[","{").replace("]","}")

pattern_commas = re.compile(", ")
matches = re.findall(pattern_commas, lst_str)
n = len(matches) - 1
output = re.sub(pattern_commas, ':{', lst_str, n).replace(",",":") + '}' * n
dictionary = ast.literal_eval(output)
print(dictionary)

輸出:

{1: {2: {3: {4: 5}}}}

編輯:在使用此答案之前,請閱讀@wjandrea 的評論。 這不適用於所有輸入。

暫無
暫無

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

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