Каков наиболее эффективный способ суммирования слова с несколькими ключами одним ключом?

1

У меня есть следующая структура 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_tmpl_id... Я использую dictcollections, но он суммирует только ключ qty, мне нужно суммировать ключ, кроме product_tmpl_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()]

Я знаю, как это сделать с помощью итерации, но пытаясь найти более питонический путь

Спасибо

РЕДАКТИРОВАТЬ:

Нужно переходить от этого:

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-2.7
python-collections

3 ответа

3
Лучший ответ

Используя базовый 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}]
1

На verbose стороне, но выполняет свою работу:

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}]
  • 0
    вот чего я пытался избежать
  • 0
    Не думайте, что есть обходной путь, если вы не пойдете по пути панд (или подобного)
0

Вы можете использовать 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}]

Ещё вопросы

Сообщество Overcoder
Наверх
Меню