在遇到条件时,我无法添加一个字典值,例如我有这个词典列表:
[{'plu': 1, 'price': 150, 'quantity': 2, 'stock': 5},
{'plu': 2, 'price': 150, 'quantity': 7, 'stock': 10},
{'plu': 1, 'price': 150, 'quantity': 6, 'stock': 5},
{'plu': 1, 'price': 200, 'quantity': 4, 'stock': 5},
{'plu': 2, 'price': 150, 'quantity': 3, 'stock': 10}
]
然后输出应如下所示:
[{'plu': 1, 'price': 150, 'quantity': 8, 'stock': 5},
{'plu': 1, 'price': 200, 'quantity': 4, 'stock': 5},
{'plu': 2, 'price': 150, 'quantity': 10, 'stock': 10}
]
只有当plu和price相同时才应该添加数量,它应该忽略key:除此之外的值(例如stock)。最有效的方法是什么?
@edit 我试过了:
import itertools as it
keyfunc = lambda x: x['plu']
groups = it.groupby(sorted(new_data, key=keyfunc), keyfunc)
x = [{'plu': k, 'quantity': sum(x['quantity'] for x in g)} for k, g in groups]
但它只适用于plu,然后我在django中制作html表时只获得数量值,其他都是空的
答案 0 :(得分:2)
您需要对组合键进行排序/ groupby
,而不仅仅是一个键。最简单/最有效的方法is with operator.itemgetter
。要保留任意stock
值,您需要使用该组两次,因此您需要将其转换为序列:
from operator import itemgetter
keyfunc = itemgetter('plu', 'price')
# Unpack key and listify g so it can be reused
groups = ((plu, price, list(g))
for (plu, price), g in it.groupby(sorted(new_data, key=keyfunc), keyfunc))
x = [{'plu': plu, 'price': price, 'stock': g[0]['stock'],
'quantity': sum(x['quantity'] for x in g)}
for plu, price, g in groups]
或者,如果每个唯一stock
/ plu
对的price
保证相同,您可以将其包含在key
中以简化问题,因此您不需要为这些团体搞砸:
keyfunc = itemgetter('plu', 'price', 'stock')
groups = it.groupby(sorted(new_data, key=keyfunc), keyfunc)
x = [{'plu': plu, 'price': price, 'stock': stock,
'quantity': sum(x['quantity'] for x in g)
for (plu, price, stock), g in groups]
或者,您可以在顶层创建getquantity = itemgetter('quantity')
(例如keyfunc
)并将sum(x['quantity'] for x in g)
更改为sum(map(getquantity, g))
,这会将工作推送到CPython中的C层,并且可以如果您的团队规模很大,请加快速度。
另一种方法是避免完全排序using collections.Counter
(or collections.defaultdict(int)
,尽管Counter
会使意图更加明确):
from collections import Counter
grouped = Counter()
for plu, price, stock, quantity in map(itemgetter('plu', 'price', 'stock', 'quantity'), new_data):
grouped[plu, price, stock] += quantity
然后转换回您的首选表单:
x = [{'plu': plu, 'price': price, 'stock': stock, 'quantity': quantity}
for (plu, price, stock), quantity in grouped.items()]
对于大型输入,这应该更快,因为它会使用O(n log n)
O(n)
次操作(大约dict
次成本)取代O(1)
排序工作。
答案 1 :(得分:1)
使用pandas
会使这成为一个微不足道的问题:
import pandas as pd
data = [{'plu': 1, 'price': 150, 'quantity': 2, 'stock': 5},
{'plu': 2, 'price': 150, 'quantity': 7, 'stock': 10},
{'plu': 1, 'price': 150, 'quantity': 6, 'stock': 5},
{'plu': 1, 'price': 200, 'quantity': 4, 'stock': 5},
{'plu': 2, 'price': 150, 'quantity': 3, 'stock': 10}]
df = pd.DataFrame.from_records(data)
# df
#
# plu price quantity stock
# 0 1 150 2 5
# 1 2 150 7 10
# 2 1 150 6 5
# 3 1 200 4 5
# 4 2 150 3 10
new_df = df.groupby(['plu','price','stock'], as_index=False).sum()
new_df = new_df[['plu','price','quantity','stock']] # Optional: reorder the columns
# new_df
#
# plu price quantity stock
# 0 1 150 8 5
# 1 1 200 4 5
# 2 2 150 10 10
最后,如果您愿意,请将其移回dict
(尽管我认为pandas
会为您提供更多处理数据元素的功能):
new_data = df2.to_dict(orient='records')
# new_data
#
# [{'plu': 1, 'price': 150, 'quantity': 8, 'stock': 5},
# {'plu': 1, 'price': 200, 'quantity': 4, 'stock': 5},
# {'plu': 2, 'price': 150, 'quantity': 10, 'stock': 10}]