data = [(0, 0, {'product_id': 6, 'qty': 1.0}), (0, 0, {'product_id': 8, 'qty': 1.0}), (0, 0, {'product_id': 7, 'qty': 2.0}), (0, 0, {'product_id': 6, 'qty': 1.0}), (0, 0, {'product_id': 8, 'qty': 1.0}), (0, 0, {'product_id': 7, 'qty': 2.0})]

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

Вывод списка должен быть:

 new_data = [(0, 0, {'product_id': 6, 'qty': 2.0}), (0, 0, {'product_id': 8, 'qty': 2.0}), (0, 0, {'product_id': 7, 'qty': 4.0})]
0
Alpesh Valaki 29 Май 2017 в 08:11

2 ответа

Лучший ответ

Я думаю, что самый простой способ - создать словарь (карту) для идентификаторов вашего продукта, извлечь данные в этот словарь, а затем создать новый список данных. Пример:

from collections import defaultdict
def mergeQty(data):
  qtyMap = defaultdict(float)
  for x, y, product in data:
    id = product['product_id']
    qty = product['qty']
    qtyMap[(x, y, id)] += qty

  return [(x, y, { 'product_id' : id, 'qty' : qty }) for (x, y, id), qty in qtyMap.iteritems()]

Обратите внимание, что это не объединит продукты, первые два значения которых отличаются (в вашем примере все они равны 0, и мы можем только догадываться, что они означают).

РЕДАКТИРОВАТЬ: Спасибо Азату за предложение defaultdict.

РЕДАКТИРОВАТЬ: сохранить неизвестные поля x и y в соответствии с предложением Куро.

3
Josh Parnell 29 Май 2017 в 05:38

Однолинейное решение:

data = [(0, 0, {'product_id': 6, 'qty': 1.0}), (0, 0, {'product_id': 8, 'qty': 1.0}),
        (0, 0, {'product_id': 7, 'qty': 2.0}), (0, 0, {'product_id': 6, 'qty': 1.0}),
        (0, 0, {'product_id': 8, 'qty': 1.0}), (0, 0, {'product_id': 7, 'qty': 2.0})]

import itertools
import functools
from operator import itemgetter

[functools.reduce(lambda x, y: (x[0], x[1], {'product_id': x[2]['product_id'], 'qty': x[2]['qty'] + y[2]['qty']}), y) for _,y in itertools.groupby(sorted(data, key=lambda x: itemgetter('product_id')(itemgetter(2)(x))),key=lambda x: itemgetter('product_id')(itemgetter(2)(x)))]
1
Alireza Afzal aghaei 31 Май 2017 в 19:31