Объединение 2 списков словарей

#python #list #dictionary

#python #Список #словарь

Вопрос:

у меня есть следующий список словарей:

 {'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumRefund': 298}
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumCashBack': 10586}
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'MasterCard', 'sumTotal': 14}
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa', 'sumTotal': 10}
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumTotal': 40}
 

как бы мне объединить их, чтобы ключ cardscheme был уникальным — это потребует объединения sumRefund и sumCashback в одну строку (пример shwon ниже), но я не могу понять это.

 {'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'MasterCard', 'sumTotal': 14}
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa', 'sumTotal': 10}
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumTotal': 40, 'sumRefund': 298, 'sumCashBack': 10586}
 

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

1. Правильный ли ваш желаемый результат? Как и в случае MasterCard с , здесь нет sumRefund and sumCashBack , но оно есть в желаемом выводе…

2. о, извините, я полностью все испортил, я отредактирую это, чтобы исправить, спасибо, что дали мне знать

3. время публикации defaultdict soln: 8.65000000000010039e-05, тогда как два цикла, опубликованные (мной :)) ниже, чем 2.3500000000176158e-05. Это важно, однако еще предстоит выяснить, содержит ли список тысячи записей, поле сужается.

Ответ №1:

Вы можете использовать метод обновления словаря вместе с defaultdict . Предполагая, что L это исходный список:

 from collections import defaultdict

cardschemes_rules = defaultdict(dict)

for dic in L:
    cardschemes_rules[dic['cardscheme']   dic['posid']].update(dic)
    
cardschemes_rules.values()
 

Как вы просили в комментарии, каждый вывод соответствует объединению ключей для данной (cardscheme, posid) пары.

Запуск этого кода со следующим L :

 L = [
    {'posid': 'A', 'cardscheme': 'Visa Debit', 'sumRefund': 2.98},
    {'posid': 'A', 'cardscheme': 'Visa Debit', 'sumCashBack': 105.86},
    {'posid': 'A', 'cardscheme': 'MasterCard', 'sumTotal': .14},
    {'posid': 'A', 'cardscheme': 'Visa Debit', 'sumTotal': .40},
    {'posid': 'B', 'cardscheme': 'Visa Debit', 'sumRefund': 298},
    {'posid': 'B', 'cardscheme': 'Visa Debit', 'sumCashBack': 10586},
    {'posid': 'B', 'cardscheme': 'Visa', 'sumTotal': 10},
]
 

Приведет к cardschemes_rules.values() :

 {'posid': 'A', 'cardscheme': 'Visa Debit', 'sumRefund': 2.98, 'sumCashBack': 105.86, 'sumTotal': 0.4}
{'posid': 'A', 'cardscheme': 'MasterCard', 'sumTotal': 0.14}
{'posid': 'B', 'cardscheme': 'Visa Debit', 'sumRefund': 298, 'sumCashBack': 10586}
{'posid': 'B', 'cardscheme': 'Visa', 'sumTotal': 10}
 

Если у вас есть коллизии имен при вводе, последняя запись в списке ввода останется (значение заменяется новым при каждом update применении).

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

1. Это отлично работает, когда есть один posid , как я мог бы разрешить присутствие нескольких posid ключей?

2. Если их несколько posid , вам нужно будет включить posid в cardschemes_rules ключ, например cardschemes_rules[dic['cardscheme'] dic['posid'] , таким образом, вы будете обновлять словари для каждой cardscheme posid пары. Подойдет любой ключ, включающий оба поля. Он просто должен быть уникальным для каждой пары cardscheme , posid .

Ответ №2:

Я бы использовал pandas:

 import pandas as pd

data = [  
    {'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumRefund': 298},
    {'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumCashBack': 10586},
    {'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'MasterCard', 'sumTotal': 14},
    {'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa', 'sumTotal': 10},
    {'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumTotal': 40}
]

df = pd.DataFrame()
for line in data:
    df = df.append(line, ignore_index=True)
df = df.fillna(0)
df = df.groupby('cardscheme').sum()

df.to_csv('test.csv')
 

Надеюсь, я помог 🙂

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

1. Это очень близко, но когда он запускается, я теряю значение posid

2. вы можете использовать список аргументов для группировки, например. df.groupby([‘cardscheme’, ‘posid’]).sum()

Ответ №3:

Пробовал с минимальными итерациями, но это лучшее, с чем я столкнулся.

Код:

 lst = [{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumRefund': 298},
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumCashBack': 10586},
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'MasterCard', 'sumTotal': 14},
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa', 'sumTotal': 10},
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumTotal': 40}]

uniq_lst = []
for dct in lst:
    updated = False
    for dct_res in uniq_lst:
        if dct_res['posid'] == dct['posid'] and dct_res['cardscheme'] == dct['cardscheme']:
            dct_res[list(dct.keys())[2]] = list(dct.values())[2]
            updated = True
            break
    else:
        uniq_lst.append(dct)
        updated = True
    if not updated:
        uniq_lst.append(dct)

for ele in uniq_lst: 
    print(ele)
 

Вывод:

 {'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa Debit', 'sumRefund': 298, 'sumCashBack': 10586, 'sumTotal': 40}
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'MasterCard', 'sumTotal': 14}
{'posid': 'AZDEMOBirminghamB134', 'cardscheme': 'Visa', 'sumTotal': 10}