Рубрики
Программирование Python

Python сравнить список сам с собой. 24.06.2021

Очередная подзадача большой задачи.

Есть список со справочниками. Нужно найти дублирующиеся подстроки по одному из ключей и взять самый поздний из них

В прошлой подзадаче я нашел дубли в списке. Сейчас мне нужно провести с ним некоторые операции:

Раньше я доставал значение одного ключа. Теперь мне нужно достать еще один ключ с датой. В моем случае, это строка. Чтобы работать с ней как с датой вызываем Datetime и преобразовываем строку в дату:

import datetime

date_st_sravn = row1.setdefault("DATE_STATUS")
date_st_sravn_to_date = datetime.datetime.strptime(date_st_sravn, '%d.%m.%Y')

Общая логика

  • В первом цикле я перебираю список словарей. На каждом шаге:
    • Достаю искомую подстроку
    • Достаю строку с датой и делаю её датой
  • Внутри первого цикла запускаю второй.
    • Для тех случаев когда я не сравниваю справочник сам с собой и подстроки равны выполняю проверку
    • Сравниваю дату текущего элемента со всеми. Если нет более поздних, записываю в новый список

Итоговый код

import datetime


# На рабочем списке показать не могу, поэтому задаю вымышленный список.
test_list = [{'FIO': 'Иванов Иван Иванович', 'LS': 123, 'CITY': 'Абакан', 'TYPE_DOG': 'ФЛ', 'STATUS': 'deleted', 'DATE_STATUS': '26.01.2021', 'STREET': 'Чертыгашева', 'HOUSE': '126', 'CORPUS': '', 'FLAT': '1', 'RESOURSE': '[ТТК] Подключение ШПД', 'CIRCUIT_ID': '20:1A:06:33:B5:48::55.33.6.31::22', 'CLSRV': '8028058', 'MAC': '201a.0633.b548', 'IP': '-', 'DATE_LAST': ''},
 {'FIO': 'Илон Иванович Маск', 'LS': 456, 'CITY': 'Абакан', 'TYPE_DOG': 'ФЛ', 'STATUS': 'deleted', 'DATE_STATUS': '29.01.2021', 'STREET': 'Чертыгашева', 'HOUSE': '126', 'CORPUS': '', 'FLAT': '60', 'RESOURSE': '[ТТК] Подключение ШПД', 'CIRCUIT_ID': '0C:80:63:C3:7F:88::55.33.6.31::1', 'CLSRV': '7893973', 'MAC': '0c80.63c3.7f88', 'IP': '-', 'DATE_LAST': 'янв.21'},
 {'FIO': 'Дональт Иванович Трамп', 'LS': 789, 'CITY': 'Абакан', 'TYPE_DOG': 'ФЛ', 'STATUS': 'deleted', 'DATE_STATUS': '14.04.2021', 'STREET': 'Чертыгашева', 'HOUSE': '126', 'CORPUS': '', 'FLAT': '16', 'RESOURSE': '[ТТК] Подключение ШПД', 'CIRCUIT_ID': '1C:7E:E5:0C:BD:EA::55.33.6.31::22', 'CLSRV': '4858373', 'MAC': '1c7e.e50c.bdea', 'IP': '-', 'DATE_LAST': 'фев.21'},
 {'FIO': 'Грета Ивановна Тумберг', 'LS': 1234, 'CITY': 'Абакан', 'TYPE_DOG': 'ФЛ', 'STATUS': 'deleted', 'DATE_STATUS': '26.01.2021', 'STREET': 'Чертыгашева', 'HOUSE': '126', 'CORPUS': '', 'FLAT': '2', 'RESOURSE': '[ТТК] Подключение ШПД', 'CIRCUIT_ID': 'E8:DE:27:9D:3A:C3::55.33.6.31::7', 'CLSRV': '4843625', 'MAC': 'e8de.279d.3ac3', 'IP': '-', 'DATE_LAST': ''},
 {'FIO': 'Бритни Ивановна Спирс', 'LS': 213232, 'CITY': 'Абакан', 'TYPE_DOG': 'ФЛ', 'STATUS': 'deleted', 'DATE_STATUS': '26.01.2021', 'STREET': 'Чертыгашева', 'HOUSE': '126', 'CORPUS': '', 'FLAT': '42', 'RESOURSE': '[ТТК] Подключение ШПД', 'CIRCUIT_ID': '2C:27:D7:01:C7:9C::55.33.6.31::15', 'CLSRV': '4839931', 'MAC': '6c62.6d92.31cd', 'IP': '-', 'DATE_LAST': ''},
 {'FIO': 'Сидоров Сидор Сидорович', 'LS': 32312321, 'CITY': 'Абакан', 'TYPE_DOG': 'ФЛ', 'STATUS': 'paused by system', 'DATE_STATUS': '21.04.2021', 'STREET': 'Чертыгашева', 'HOUSE': '126', 'CORPUS': '', 'FLAT': '40', 'RESOURSE': '[ТТК] Подключение ШПД', 'CIRCUIT_ID': '08:C6:B3:2D:1C:27::55.33.6.31::7', 'CLSRV': '10469345', 'MAC': '08c6.b32d.1c27', 'IP': '-', 'DATE_LAST': 'июн.21'},
 {'FIO': 'Никоноров Никонор Никонорович', 'LS': 321321312, 'CITY': 'Абакан', 'TYPE_DOG': 'ФЛ', 'STATUS': 'paused by system', 'DATE_STATUS': '26.01.2018', 'STREET': 'Чертыгашева', 'HOUSE': '126', 'CORPUS': '', 'FLAT': '1', 'RESOURSE': '[ТТК] Подключение ШПД', 'CIRCUIT_ID': 'E4:6F:13:B7:FA:B1::55.33.6.31::8', 'CLSRV': '8108957', 'MAC': 'e46f.13b7.fab1', 'IP': '-', 'DATE_LAST': ''}]

clean_list = []  # В этот список буду собирать нужные мне значения

# В цикле сравниваю элементы списка между собой
for row in test_list:
    circuit = row.setdefault("CIRCUIT_ID")  # Достаю из словаря значение ключа CIRCUIT_ID
    str_ip_port = str_circuit[circuit.index("::")+2:]  # этой строкой я делаю срез от найденной позиции +2
    date_st = row.setdefault("DATE_STATUS")  # достаю значение ключа DATE_STATUS. Это строка, а мне нужна дата
    date_st_to_date = datetime.datetime.strptime(date_st, '%d.%m.%Y')  # Преобразовываю строку в дату
    for row1 in test_list:
        date_st_sravn = row1.setdefault("DATE_STATUS")
        date_st_sravn_to_date = datetime.datetime.strptime(date_st_sravn, '%d.%m.%Y')
        str_circuit_sravn = row1.setdefault("CIRCUIT_ID")
        str_ip_sravn = str_circuit_sravn[str_circuit_sravn.index("::")+2:] # беру срез[c позиции двух двоеточий+2 до конца]
        if (str_circuit != str_circuit_sravn) and (str_ip_port == str_ip_sravn):  # Здесь проверяю равенство искомых 
            # подстрок. Но(первое условие) не сравниваю элементы списка между собой 
            if date_st_to_date > date_st_sravn_to_date:  # Здесь я выбираю из дублирующихся элементов один с поздней датой
                clean_list.append(row)

# Построчно вывожу полученный список
for row2 in clean_list:
    print(row2)

Вроде всё работает как нужно.

Рубрики
Программирование Python

23.06.2021 найти дубли в списке из справочников Python

Это один из кусочков моего первого боевого кода.

У меня есть список из словарей test_list. Реальные данные показать не могу. Так как там содержится конфиденциальная информация.

В каждом словаре несколько записей, одна из которых в формате: ‘CIRCUIT_ID’: ‘E4:6F:13:B7:FA:B1::55.33.6.31::8’.

Одна из подзадач: перебрать все словари из списка и найти дубли по частичному вхождению в ключе словаря. Нужно достать значение ключа, формата ‘E4:6F:13:B7:FA:B1::55.33.6.31::8’, достать оттуда всё что идёт после первых двойных двоеточий 55.33.6.31::8 и проверить есть ли в других словарях списка такие же подстроки.

Для тех кто немного понимает в сетях. У меня большая база данных с данными по мак адресам, коммутаторам и портам. Текущая подзадача вытащить дублирующие строки IP порт. Чтобы понять по каким портам и на каких коммутаторах, больше одной записи. Исходный код ниже.

test_list = [{},{},{},{},{},{},{},{}]

for row in test_list:
    circuit = row.setdefault("CIRCUIT_ID")
    str_circuit = str(circuit)
    str_ip_port = str_circuit[str_circuit.index("::")+2:] # этой строкой я делаю срез от найденной позиции +2
    for row1 in test_list:
        str_circuit_sravn = row1.setdefault("CIRCUIT_ID")
        str_ip_sravn = str_circuit_sravn[str_circuit_sravn.index("::")+2:] # беру срез[c позиции двух двоеточий+2 до конца]
        if (str_circuit != str_circuit_sravn) and (str_ip_port == str_ip_sravn) :
            print(str_ip_port)