繁体   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