сравните два 2d списка в списке и выведите разные строки. Но без одного столбца

#python #list #multidimensional-array

#python #Список #многомерный массив

Вопрос:

следующее:

 gnucashumsaetze = [
 ['2020-11-27', 'Essen', '4.53'],
 ['2020-11-27', 'Essen', '10.67'],
 ['2020-11-30', 'Essen', '4.80'],
 ['2020-11-30', 'Lebensmittel', '2.78'],
 ['2020-11-30', 'Essen', '2.31'],
 ['2020-11-30', 'Kosmetik', '5.58'],
 ['2020-12-01', 'Essen', '11.23'],
]

onlineumsaetze = [
['2020-11-27', 'EDEKA ERNST HAUPTBAHNH  / MUENCHEN', '4.53']
['2020-11-27', 'Netto Marken-Discount  / Ingolstadt', '10.67']
['2020-11-30', 'MUELLER GMBH amp; CO.KG  / NUERNBERG', '4.80']
['2020-11-30', 'Netto Marken-Discount  / Frankfurt', '2.31']
['2020-11-30', 'Rossmann 2380  / Ingolstadt', '5.58']
['2020-11-30', 'ALIEXPRESS.COM  / Luxembourg', '22.46']
['2020-12-01', 'EDEKA BRAUN  / INGOLSTADT', '11.23']
['2020-12-02', 'EDEKA ERNST HAUPTBAHNH  / MUENCHEN', '7.03']
]
 

я хотел бы сравнить два 2d-списка и вывести разные. Но второй столбец (строка [1]) сравнивать не следует. Вот так:

 ['2020-11-30', 'ALIEXPRESS.COM  / Luxembourg', '22.46']
['2020-12-01', 'EDEKA BRAUN  / INGOLSTADT', '11.23']
['2020-12-02', 'EDEKA ERNST HAUPTBAHNH  / MUENCHEN', '7.03']
 

то, что я уже пробовал, это; к сожалению, катастрофа:

 fehlende_rows = (set((row[0] for row in onlineumsaetze),(row[2] for row in onlineumsaetze)) - set((row[0] for row in gnucashumsaetze),(row[2] for row in gnucashumsaetze)))
print(fehlende_rows)
 

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

1. Разрешено ли вам изменять структуру данных? Например, преобразовать эти списки в dicts?

2. Что значит «выводить разные»? Вы имеете в виду, что хотите вывести строку onlineumsaetze только из того, что gnucashumsaetze не содержит строк с одинаковой датой и числовым значением в третьем столбце?

3. @Diptangsu Госвами, К сожалению, нет. Эти данные копируются с веб-страницы HTML.

4. @Pranav Hosangadi, да, точно, в первом и третьем.

Ответ №1:

Я нахожу очень полезным сначала записать полный цикл, а затем, по возможности, свести его к пониманию списка.

Вероятно, лучшим способом сделать это было бы выполнить итерацию gnucashumsaetze и создать словарь string->set, который содержит даты в качестве ключей и числа в качестве элементов набора.

 gnucashumsaetze_dict = {}
for g in gnucashumsaetze:
    date, val = g[0], g[2]
    # Maybe you want to do val = float(g[2]) instead?
    if date not in gnucashumsaetze_dict:
        gnucashumsaetze_dict[date] = set()
    gnucashumsaetze_dict[date].add(val)
 

gnucashumsaetze_dict теперь:

 {'2020-11-27': {'10.67', '4.53'},
 '2020-11-30': {'2.31', '2.78', '4.80', '5.58'},
 '2020-12-01': {'11.23'}}
 

Затем выполните итерацию по каждой строке onlineumsaetze и добавьте ее в новый список, только если выполнено требуемое условие.

 new_onlineumsaetze = []
for o in onlineumsaetze:
    date, val = o[0], o[2]
    # if date is not in gnucashumsaetze_dict, return empty set
    vals = gnucashumsaetze_dict.get(date, set()) 
    if val not in vals:
        new_onlineumsaetze.append(o)
 

new_onlineumsaetze теперь:

 [['2020-11-30', 'ALIEXPRESS.COM  / Luxembourg', '22.46'],
 ['2020-12-02', 'EDEKA ERNST HAUPTBAHNH  / MUENCHEN', '7.03']]
 

['2020-12-01', 'EDEKA BRAUN / INGOLSTADT', '11.23'] Строка пропускается, потому gnucashumsaetze что содержит запись для ['2020-12-01', 'Essen', '11.23']

Теперь, когда вы написали это как обычный цикл for, легче свести это к пониманию списка.

 new_onlineumsaetze = [o for o in onlineumsaetze if o[2] not in gnucashumsaetze_dict.get(o[0], set())]
 

Ответ №2:

Для решения этой проблемы я буду использовать понимание списка

сначала создайте два набора, используя только column0 и column2

 gnucashumsaetze_set = set([(row[0], row[2]) for row in gnucashumsaetze])
onlineumsaetze_set = set([(row[0], row[2]) for row in onlineumsaetze])
 

Затем мы получаем разницу между этими двумя наборами

 diff_ = onlineumsaetze_set.difference(gnucashumsaetze_set)
 

для получения конечного результата мы ищем строки в onlineumsaetze, которые совпадают в column0 и column2 с полученными нами данными.

 res = [row for row in onlineumsaetze if (row[0], row[2]) in diff_]

print(res)
 

результат

 [['2020-11-30', 'ALIEXPRESS.COM  / Luxembourg', '22.46'], ['2020-12-02', 'EDEKA ERNST HAUPTBAHNH  / MUENCHEN', '7.03']]