Как я могу объединить два списка диктов в python с потенциально разными парами ключ-значение?

#python #dictionary

Вопрос:

Допустим, у меня есть два списка диктов, оба из которых являются КВП в разных диктах.

 oldItemsBought = [{
   "name" : <item name>,
   "quantity": <item quantity>,
   "billed": <item bill amount (qty * price)>
}
{
   "name" : <item name>,
   "quantity": <item quantity>,
   "billed": <item bill amount (qty * price)>
}.....]
newItemsBought = [{
   "name" : <item name>,
   "quantity": <item quantity>,
   "billed": <item bill amount (qty * price)>
}
{
   "name" : <item name>,
   "quantity": <item quantity>,
   "billed": <item bill amount (qty * price)>
}.....]
 

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

Есть ли более простой способ выполнить эту операцию добавления или обновления?

Комментарии:

1. Просто закодируйте это так же, как вы сделали бы это как человек. Что вы делаете, шаг за шагом?

2. "items":[...] это даже недопустимый синтаксис Python, не так ли?

3. Да, это недействительно. Разве пошаговая итерация с циклами не займет много времени? (и в конце концов слишком запутанно, так как это была моя первая попытка)

4. Эмпирическое правило: сначала заставьте его работать, а затем оптимизируйте, если он работает слишком медленно. И код, похоже, работает медленнее, чем обычно, для зацикливания каждого списка покупок на самом деле.

5. Отнимает время или нет: если это работает, это лучше, чем текущее решение. Это не будет сбивать с толку, так как каждый может понять ваши индивидуальные шаги вместо того, чтобы иметь какое-то запутанное питоновское решение «все в одной строке».

Ответ №1:

 newList = []

is_dublicate = False

for item in newItemBought:
    for old_item in oldItemsBought:
        if item['name'] == old_item['name']:
            old_item['quantity']  = item['quantity']
            newList.append(old_item)
            oldItemsBought.remove(old_item)
            is_dublicate = True
            break

    if not is_dublicate:
        newList.append(item)

    is_dublicate = False


for item in oldItemsBought:
    newList.append(item)


print(newList)
 

Ответ №2:

 for olditem in oldItemsBought:
    for newitem in newItemsBought:
        if olditem["name"]==newitem["name"]:
            newitem["quantity"] =olditem["quantity"]
            newitem["billed"] =olditem["billed"]
            break
    else:
        print(olditem["name"],newitem["name"],olditem)
        newItemsBought.append(olditem)
 

Ответ №3:

Попробуйте использовать groupby , чтобы получить все словари с одинаковым именем:

 from itertools import groupby
from operator import itemgetter

res = [{'name': k,
        'quantity': sum(item['quantity'] for item in g),
        'billed': sum(item['billed'] for item in g)}
       for k, g in groupby(oldItemsBought   newItemsBought, itemgetter('name'))]