Удалите дубликаты в списке на python

#python

Вопрос:

У меня есть динамический список :

 [{'dashboard': 'AG', 'end_date': '2021-06-17 13:13:43', 'location': 'EC amp; pH Reading', 'zone_name': 'Zone 1 Left'}, 

{'dashboard': 'AG', 'end_date': '2021-06-17 12:40:06', 'location': 'Harvest', 'zone_name': 'Zone 2 Left'}, 

{'dashboard': 'AG', 'end_date': '2021-06-16 15:52:52', 'location': 'Harvest', 'zone_name': 'Zone 1 Left' }, 

{'dashboard': 'AG', 'end_date': '2021-06-16 15:45:51', 'location': 'Harvest', 'zone_name': 'Zone 1 Left'}]
 

Я хочу удалить дубликаты на основе имени зоны и местоположения.
В zone_name есть 3 значения. Я хочу удалить старую. Я отсортировал, используя конечную дату. То есть последнее будет на вершине.
Теперь мне нужно удалить повторяющееся значение на основе имени зоны и местоположения.

Это то, что я пробовал:

 final_zone = []
res_list = []
for i in sortedArray:
     if i["location"] not in final_zone:
          sch.append(i)
          final_zone.append(i["location"])
 

Какие изменения мне нужно сделать, чтобы удалить дубликат на основе имени зоны и местоположения.

То есть в левой зоне 1 есть 3 значения , мне нужно последнее

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

1. Последняя. Я отсортировал это по дате окончания

Ответ №1:

Для общего подхода с несортированным списком:

 from itertools import groupby
from operator import itemgetter

# sorting and grouping functions
f_sort = itemgetter("location", "zone_name", "end_date")  # sort by descending
f_group = itemgetter("location", "zone_name")  # group sorted by

result = [
    next(g) for _, g in  # only take latest of each group
    groupby(sorted(array, key=f_sort, reverse=True), key=f_group)
]
 

Вот некоторая документация по используемым utils (все они очень удобны во многих случаях использования):

Ответ №2:

 clean_list=[]

for elem in lst:
    # control if an element with the same zone name and location
    # is yet present in the clean list
    yet_present= len([el for el in clean_list
                if el['zone_name']==elem['zone_name']
                if el['location']==elem['location']])>0
    if not yet_present:
        clean_list.append(elem)
 

выход:

 [{'dashboard': 'AG',
  'end_date': '2021-06-17 13:13:43',
  'location': 'EC amp; pH Reading',
  'zone_name': 'Zone 1 Left'},
 {'dashboard': 'AG',
  'end_date': '2021-06-17 12:40:06',
  'location': 'Harvest',
  'zone_name': 'Zone 2 Left'},
 {'dashboard': 'AG',
  'end_date': '2021-06-16 15:52:52',
  'location': 'Harvest',
  'zone_name': 'Zone 1 Left'}]
 

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

1. Вы спасли мне день. Спасибо

2. Если мой ответ полезен, пожалуйста, поддержите и/или примите его.

3. Нужно 15 репутации, чтобы поднять голос. у меня этого нет, поэтому я не могу этого сделать

4. Вы можете принять его (инструкции: meta.stackexchange.com/a/5235/645001 )

Ответ №3:

Вы можете просто просмотреть список и запомнить индексы, которые хотите сохранить.

 keepers = {}
for i in range(len(sorted_array)):
    keepers(sorted_array[i]['location'])=i ## Will be overwritten if the zone_name repeats

final_array = []
for i in keepers.values():
    final_array.append(sorted_array[i])
 

В качестве бонуса вы получаете список всех зон внутри keepers.keys() .

Но ваш подход также может сработать. Просто измените sch.append(i) res_list.append(i) и измените порядок iterable ( for i in sorted_array[::-1] ), чтобы сохранялся последний, а не первый.

Ответ №4:

Другие ответы работают, но я хочу добавить решение, используя Pandas

вы можете создать фрейм данных из своего списка словарей:

 import pandas as pd
d = [{'dashboard': 'AG', 'end_date': '2021-06-17 13:13:43', 'location': 'EC amp; pH Reading', 'zone_name': 'Zone 1 Left'}, {'dashboard': 'AG', 'end_date': '2021-06-17 12:40:06', 'location': 'Harvest', 'zone_name': 'Zone 2 Left'}, 

{'dashboard': 'AG', 'end_date': '2021-06-16 15:52:52', 'location': 'Harvest', 'zone_name': 'Zone 1 Left' }, 

{'dashboard': 'AG', 'end_date': '2021-06-16 15:45:51', 'location': 'Harvest', 'zone_name': 'Zone 1 Left'}]
df = pd.DataFrame(d)
 

Вот как выглядит df:

 dashboard             end_date         location    zone_name
0        AG  2021-06-17 13:13:43  EC amp; pH Reading  Zone 1 Left
1        AG  2021-06-17 12:40:06          Harvest  Zone 2 Left
2        AG  2021-06-16 15:52:52          Harvest  Zone 1 Left
3        AG  2021-06-16 15:45:51          Harvest  Zone 1 Left
 

Что-то вроде таблицы в Excel.

Теперь с помощью одной строки вы можете делать именно то, что хотите:

 df.sort_by("end_date").drop_duplicates(["location", "zone_name"], keep="last")
 

выход:

   dashboard             end_date         location    zone_name
2        AG  2021-06-16 15:52:52          Harvest  Zone 1 Left
1        AG  2021-06-17 12:40:06          Harvest  Zone 2 Left
0        AG  2021-06-17 13:13:43  EC amp; pH Reading  Zone 1 Left