扁平化包含嵌套字典列表的字典列表的最佳方法?



我有一个字典列表,其中一个字典值也是字典列表。我想把它平铺成一个字典列表。

我有一些工作代码,想知道是否有一种更习惯的方法来实现这一点。

下面是我的代码:
from pprint import pprint
transactions = [
{
"Customer": "Leia",
"Store": "Hammersmith",
"Basket": "basket1",
"items": [
{"Product": "Cheddar", "Quantity": 2, "GrossSpend": 2.50},
{"Product": "Grapes", "Quantity": 1, "GrossSpend": 3.00},
],
},
{
"Customer": "Luke",
"Store": "Ealing",
"Basket": "basket2",
"items": [
{
"Product": "Custard Creams",
"Quantity": 1,
"GrossSpend": 3.00,
}
],
},
]
flattened_transactions = []
for transaction in transactions:
flattened_transactions.extend(
{
"Customer": transaction["Customer"],
"Store": transaction["Store"],
"Basket": transaction["Basket"],
"Product": item["Product"],
"Quantity": item["Quantity"],
"GrossSpend": item["GrossSpend"],
}
for item in transaction["items"]
)
pprint(flattened_transactions)

输出:

[{'Basket': 'basket1',
'Customer': 'Leia',
'GrossSpend': 2.5,
'Product': 'Cheddar',
'Quantity': 2,
'Store': 'Hammersmith'},
{'Basket': 'basket1',
'Customer': 'Leia',
'GrossSpend': 3.0,
'Product': 'Grapes',
'Quantity': 1,
'Store': 'Hammersmith'},
{'Basket': 'basket2',
'Customer': 'Luke',
'GrossSpend': 3.0,
'Product': 'Custard Creams',
'Quantity': 1,
'Store': 'Ealing'}]

是否有更好的方法来实现这一点?

我会使用列表推导式。

[{'Customer': d['Customer'], 
'Store':    d['Store'], 
'Basket':   d['Basket'], 
**d2} 
for d in transactions 
for d2 in d['items']]
# [{'Customer': 'Leia', 'Store': 'Hammersmith', 'Basket': 'basket1', 
#   'Product': 'Cheddar', 'Quantity': 2, 'GrossSpend': 2.5}, 
#  {'Customer': 'Leia', 'Store': 'Hammersmith', 'Basket': 'basket1', 
#   'Product': 'Grapes', 'Quantity': 1, 'GrossSpend': 3.0},
#  {'Customer': 'Luke', 'Store': 'Ealing', 'Basket': 'basket2', 
#   'Product': 'Custard Creams', 'Quantity': 1, 'GrossSpend': 3.0}]

如果'items'键不存在或为空,则使用dict.get键,默认值为[]

[{'Customer': d['Customer'], 
'Store':    d['Store'], 
'Basket':   d['Basket'], 
**d2} 
for d in transactions 
for d2 in d.get('items', [])]

或者更灵活,生成一个包含顶级字典和嵌套字典中的所有键的字典,然后使用字典理解删除多余的'items'键。

[{k: v 
for k, v in d3.items() 
if k != 'items'} 
for d in transactions 
for d2 in d.get('items', []) 
for d3 in ({**d, **d2},)]

你的代码看起来不错,我已经修改了一点,如果你认为我们可以优化行。处理了输入中没有items的情况。

flattened_transactions = []
for transaction in transactions:
items = transaction.pop("items", [])
for item in items:
for key, value in item.items():
transaction[key] = value
flattened_transactions.append(transaction)
else:
flattened_transactions.append(transaction)
pprint(flattened_transactions)

如果你只是想让列表变平,可以用下面的代码来完成:

ouput = []
for transaction in transactions:
output = [*output, *transaction]

python中的*操作符返回迭代器的值,就像在带大括号/尖括号的迭代器中一样。它相当于javascript中的...(spread)运算符。更多细节见文档。

最新更新