将列表列表转换为Python中的词典
我正在尝试将列表数据结构转换为字典字典 该列表定义如下:将列表列表转换为Python中的词典,python,python-3.x,list,dictionary,nested,Python,Python 3.x,List,Dictionary,Nested,我正在尝试将列表数据结构转换为字典字典 该列表定义如下: l = [ ['PP','Ear-rings', 'Holesovice', 2000], ['PP','Skirts', 'Holesovice', 1000], ['PP','Dresses', 'E-shop', 1500], ['BM','Butterfly', 'Holesovice', 1600] ] #{'PP' : {'Holesovice' : {'Ear-rings' : 2000, 'Skirts'
l = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]
#{'PP' : {'Holesovice' : {'Ear-rings' : 2000, 'Skirts' : 1000},
# 'E-shop' : {'Dresses' : 1500}},
# 'BM' : {'Holesovice' : {'Butterfly' : 1600}}
#}
我的目标是使词典结构如下:
l = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]
#{'PP' : {'Holesovice' : {'Ear-rings' : 2000, 'Skirts' : 1000},
# 'E-shop' : {'Dresses' : 1500}},
# 'BM' : {'Holesovice' : {'Butterfly' : 1600}}
#}
此代码位不返回所需的输出:
labels_d = {}
items_d = {}
shops_d = {}
for index, row in enumerate(l):
items_d[row[1]] = row[3]
shops_d[row[2]] = items_d
labels_d[row[0]] = shops_d
print(labels_d)
我找到了一些关于将列表转换为词典的帖子,但是我没有按照我想要的方式来工作。有什么“干净”的方法可以实现上面发布的结构吗?您可以使用无限嵌套的
defaultdict
技巧:
from collections import defaultdict
def nested_dict():
return defaultdict(nested_dict)
nd = nested_dict()
for a, b, c, d in l:
nd[a][c][b] = d
您可以使用
collections.defaultdict
和迭代。在这种情况下,您可以精确地定义一个嵌套字典来反映您的数据结构
from collections import defaultdict
L = [['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]]
d = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
for code, item, shop, value in L:
d[code][shop][item] = value
结果
defaultdict({'BM': defaultdict({'Holesovice': defaultdict(int, {'Butterfly': 1600})}),
'PP': defaultdict({'E-shop': defaultdict(int, {'Dresses': 1500}),
'Holesovice': defaultdict(int,
{'Ear-rings': 2000, 'Skirts': 1000})})})
使用是创建固定深度的嵌套词典的一种好方法
l = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]
d = {}
for tag, item, source, qty in l:
d.setdefault(tag, {}).setdefault(source, {})[item] = qty
class NestedDict(dict):
def __getitem__(self, item):
if item not in self:
self[item] = NestedDict()
return super().__getitem__(item)
d = NestedDict()
for tag, item, source, qty in l:
d[tag][source][item] = qty
输出
一般化
通过构建一个嵌套字典类,放弃对固定深度的要求,可以使上述解决方案更具通用性
l = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]
d = {}
for tag, item, source, qty in l:
d.setdefault(tag, {}).setdefault(source, {})[item] = qty
class NestedDict(dict):
def __getitem__(self, item):
if item not in self:
self[item] = NestedDict()
return super().__getitem__(item)
d = NestedDict()
for tag, item, source, qty in l:
d[tag][source][item] = qty
还要注意的是,类方法是创建的,因此它仅在键不存在时创建对象,而
setdefault
方法在每次访问时都创建一个空的dict
。这里发布了一个编写新词典的非常简单的方法:
def toNested1(l):
def addKeyDict(map,key):
if key not in map:
item = map[key] = {}
return item
return map[key]
zz = {}
for a0,a1,a2,a3 in l :
addKeyDict( addKeyDict( zz, a0) , a2 )[a1] = a3
return zz
如果列表每行中的项目不在字典的相应深度,只需将键值对添加/追加到dict
代码:
list = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]
dicta = {}
for row in list:
if row[0] not in dicta.keys():
dicta[row[0]] = {row[2]:{row[1]:row[3]}}
continue
if row[2] not in dicta[row[0]].keys():
dicta[row[0]][row[2]] = {row[1]:row[3]}
continue
if row[1] not in dicta[row[0]][row[2]].keys():
dicta[row[0]][row[2]][row[1]] = row[3]
print(dicta)
{'BM': {'Holesovice': {'Butterfly': 1600}},
'PP': {'E-shop': {'Dresses': 1500},
'Holesovice': {'Ear-rings': 2000, 'Skirts': 1000}}}
输出:
list = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]
dicta = {}
for row in list:
if row[0] not in dicta.keys():
dicta[row[0]] = {row[2]:{row[1]:row[3]}}
continue
if row[2] not in dicta[row[0]].keys():
dicta[row[0]][row[2]] = {row[1]:row[3]}
continue
if row[1] not in dicta[row[0]][row[2]].keys():
dicta[row[0]][row[2]][row[1]] = row[3]
print(dicta)
{'BM': {'Holesovice': {'Butterfly': 1600}},
'PP': {'E-shop': {'Dresses': 1500},
'Holesovice': {'Ear-rings': 2000, 'Skirts': 1000}}}
如果你找到了一些帖子,那么你肯定试过什么了,即使它坏了?每次你调用
setdefault
,看到一个新的对象被创建,这真的让我头疼,尽管这是一个很好的解决方案。@OlivierMelançon他们的意思是NestedDict()无论项
是否已经有一个值,这有点不雅观,
都会被调用。@Mad物理学家这是用一般方法解决的。我知道这个解决方案,我相信你也知道。我喜欢你原来的答案,因为它很简单。我的评论只是对setdefault
的普遍不满。如果有另一个方法可以接受可调用的实例而不是预构造的实例,那就太好了。也许现在是开始的好时机。我会先看看我是否能想出一个简单的实现。我也喜欢这个。“我觉得如果你把嵌套的dict变成一个类而不是一个工厂,那会更整洁一些。”OlivierMelançon说,在一个类中以如此整洁的方式使用递归逻辑肯定是一个挑战。毕竟,defaultdict
构造函数的参数是默认工厂;-)@schwobaseggl它实际上相当简单,因为工厂存储为实例参数<代码>类NestedDict(defaultdict):def_uuinit_uu(self):self.default_factory=NestedDict@OlivierMelançon True,我也喜欢这样。当然,这个答案是好的。但我确实认为重要的是要注意到这与我非常相似但更精确的答案之间的区别。当您检查一个键nd['key1']['key2']['key3']
并且它不存在时,您将得到一个空字典{}
,而在我的解决方案中,您得到的是0
。从概念上讲,它可能是相关的,因为您可能不期望{}
。我花了一些时间才注意到它,但在dict的底部返回0既微妙又简洁