Python 用一个键对多个键的dict求和最有效的方法是什么?
我有下面的dict结构Python 用一个键对多个键的dict求和最有效的方法是什么?,python,python-2.7,python-collections,Python,Python 2.7,Python Collections,我有下面的dict结构 product1 = {'product_tmpl_id': product_id, 'qty':product_uom_qty, 'price':price_unit, 'subtotal':price_subtotal, 'total':price_total, } 然后是产品列表,列表中的每一项都是具有上述结构的dict list_ = [product1,product2,product3,.....] 我需要对列表中的项目求和,按键product\u tmp
product1 = {'product_tmpl_id': product_id,
'qty':product_uom_qty,
'price':price_unit,
'subtotal':price_subtotal,
'total':price_total,
}
然后是产品列表,列表中的每一项都是具有上述结构的dict
list_ = [product1,product2,product3,.....]
我需要对列表中的项目求和,按键product\u tmpl\u id
分组。。。我正在使用dictcollections,但它只对数量键求和,我需要求和键,除了product\u tmpl\u id
,这是分组依据的标准
c = defaultdict(float)
for d in list_:
c[d['product_tmpl_id']] += d['qty']
c = [{'product_id': id, 'qty': qty} for id, qty in c.items()]
我知道如何使用for迭代来实现它,但我试图寻找一种更具python风格的方法
谢谢
编辑:
我们需要的是通过以下途径:
lst = [
{'Name': 'A', 'qty':100,'price':10},
{'Name': 'A', 'qty':100,'price':10},
{'Name': 'A', 'qty':100,'price':10},
{'Name': 'B', 'qty':100,'price':10},
{'Name': 'C', 'qty':100,'price':10},
{'Name': 'C', 'qty':100,'price':10},
]
对此
group_lst = [
{'Name': 'A', 'qty':300,'price':30},
{'Name': 'B', 'qty':100,'price':10},
{'Name': 'C', 'qty':200,'price':20},
]
使用基本的Python,这并没有得到太多的改进。你可以用
itertools.groupby
一起破解一些东西,但这会很难看,而且可能会更慢,当然也不太清晰
然而,正如@9769953所建议的,Pandas是处理这种结构化表格数据的好软件包
In [1]: import pandas as pd
In [2]: df = pd.DataFrame(lst)
Out[2]:
Name price qty
0 A 10 100
1 A 10 100
2 A 10 100
3 B 10 100
4 C 10 100
5 C 10 100
In [3]: df.groupby('Name').agg(sum)
Out[3]:
price qty
Name
A 30 300
B 10 100
C 20 200
如果不想将数据保留为数据帧,则只需额外添加一点mojo:
In [4]: grouped = df.groupby('Name', as_index=False).agg(sum)
In [5]: list(grouped.T.to_dict().values())
Out[5]:
[{'Name': 'A', 'price': 30, 'qty': 300},
{'Name': 'B', 'price': 10, 'qty': 100},
{'Name': 'C', 'price': 20, 'qty': 200}]
使用基本的Python,这并没有得到太多的改进。你可以用
itertools.groupby
一起破解一些东西,但这会很难看,而且可能会更慢,当然也不太清晰
然而,正如@9769953所建议的,Pandas是处理这种结构化表格数据的好软件包
In [1]: import pandas as pd
In [2]: df = pd.DataFrame(lst)
Out[2]:
Name price qty
0 A 10 100
1 A 10 100
2 A 10 100
3 B 10 100
4 C 10 100
5 C 10 100
In [3]: df.groupby('Name').agg(sum)
Out[3]:
price qty
Name
A 30 300
B 10 100
C 20 200
如果不想将数据保留为数据帧,则只需额外添加一点mojo:
In [4]: grouped = df.groupby('Name', as_index=False).agg(sum)
In [5]: list(grouped.T.to_dict().values())
Out[5]:
[{'Name': 'A', 'price': 30, 'qty': 300},
{'Name': 'B', 'price': 10, 'qty': 100},
{'Name': 'C', 'price': 20, 'qty': 200}]
在冗长的方面,但完成了工作:
group_lst = []
lst_of_names = []
for item in lst:
qty_total = 0
price_total = 0
# Get names that have already been totalled
lst_of_names = [item_get_name['Name'] for item_get_name in group_lst]
if item['Name'] in lst_of_names:
continue
for item2 in lst:
if item['Name'] == item2['Name']:
qty_total += item2['qty']
price_total += item2['price']
group_lst.append(
{
'Name':item['Name'],
'qty':qty_total,
'price':price_total
}
)
pprint(group_lst)
输出:
[{'Name': 'A', 'price': 30, 'qty': 300},
{'Name': 'B', 'price': 10, 'qty': 100},
{'Name': 'C', 'price': 20, 'qty': 200}]
在冗长的方面,但完成了工作:
group_lst = []
lst_of_names = []
for item in lst:
qty_total = 0
price_total = 0
# Get names that have already been totalled
lst_of_names = [item_get_name['Name'] for item_get_name in group_lst]
if item['Name'] in lst_of_names:
continue
for item2 in lst:
if item['Name'] == item2['Name']:
qty_total += item2['qty']
price_total += item2['price']
group_lst.append(
{
'Name':item['Name'],
'qty':qty_total,
'price':price_total
}
)
pprint(group_lst)
输出:
[{'Name': 'A', 'price': 30, 'qty': 300},
{'Name': 'B', 'price': 10, 'qty': 100},
{'Name': 'C', 'price': 20, 'qty': 200}]
您可以使用
defaultdict
和Counter
>>> from collections import Counter, defaultdict
>>> cntr = defaultdict(Counter)
>>> for d in lst:
... cntr[d['Name']].update(d)
...
>>> res = [dict(v, **{'Name':k}) for k,v in cntr.items()]
>>> pprint(res)
[{'Name': 'A', 'price': 30, 'qty': 300},
{'Name': 'C', 'price': 20, 'qty': 200},
{'Name': 'B', 'price': 10, 'qty': 100}]
您可以使用
defaultdict
和Counter
>>> from collections import Counter, defaultdict
>>> cntr = defaultdict(Counter)
>>> for d in lst:
... cntr[d['Name']].update(d)
...
>>> res = [dict(v, **{'Name':k}) for k,v in cntr.items()]
>>> pprint(res)
[{'Name': 'A', 'price': 30, 'qty': 300},
{'Name': 'C', 'price': 20, 'qty': 200},
{'Name': 'B', 'price': 10, 'qty': 100}]
再也不会像蟒蛇一样了。您的实现很好。您的替代方案是寻找处理此类数据结构的库,例如Pandas。对列求和的代码总体上会更简单、更快。Aran-Fey我的实现不起作用,因为它只求和,一个键“数量”,我需要求和“数量”、“总数”、“小计”、“单价”,它不会变得更像Python。您的实现很好。您的替代方案是寻找处理此类数据结构的库,例如Pandas。总的来说,对一列求和的代码会更简单、更快。Aran-Fey我的实现不起作用,因为它只是求和,一个键“数量”,我需要求和“数量”、“总数”、“小计”、“单价”,这就是我试图避免的。除非你使用熊猫(或类似的东西),否则不要认为有一种类似的方法路线这是我试图避免的。我不认为有一个蟒蛇式的方法可以绕过它,除非你选择熊猫(或类似的)路线