我有一个字典列表,其中一个字典值也是字典列表。我想把它平铺成一个字典列表。
我有一些工作代码,想知道是否有一种更习惯的方法来实现这一点。
下面是我的代码: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)运算符。更多细节见文档。