[英]Convert nested list to dict where first element of list is key for dict
[英]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.