Как сравнить два вложенных списка?

#python #nested-loops #nested-lists

#python #вложенные циклы #вложенные списки

Вопрос:

У меня есть два вложенных списка. Оба списка очень похожи, они представляют собой разные версии одного и того же файла, написанные друг над другом.

Структура списка выглядит следующим образом list = [[name, version, id],[name, version, id], ...]

 list_1 = [
['mipl-abnd','v1.0.2','eelp234'],
['mipl-avfd','v1.1.5','32fv423'],
['mipl-awsd','v9.0.2','234eelp'],
['mipl-tgfd','v3.0.0','124fdge'],
['mipl-hrdss','v1.0.2','543rfd3'],
['mipl-oldss','v1.0.2','eelp234']] 

list_2 = [
['mipl-abnd','v1.0.2','eelp234'],
['mipl-avfd','v1.1.6','3254323'],
['mipl-awsd','v9.0.2','234eelp'],
['mipl-tgfd','v3.0.0','124fdge'],
['mipl-hrdss','v1.0.2','543rfd3'],
['mipl-newss','v1.0.2','eelp234']] 
  

Я хочу повторить и сравнить list_1 , существуют ли имена в list_2 , и если это так, если версия этого компонента в list_1 не равна версии компонента в list_2 (если есть обновление версии библиотеки), затем выведите newlist_1 = [name, old version, new version, old id, new id] для всех уникальных случаев.

Если в есть имя list_1 , которого в не существует list_2 , что означает, что библиотека устарела, в этом случае новый список вывода должен содержать newlist_2 = [name, old version, 'deprecated', old id, 'deprecated'] .

Если в есть имя list_2 , которого в не существует list_1 , что означает, что библиотека добавлена заново, в этом случае новый список вывода должен содержать newlist_3 = [name, 'new', new version, new, new id] .

Конечный результат должен состоять из 3 списков и должен получить:

 newlist_1 = ['mipl-avfd', 'v1.1.5', 'v1.1.6','32fv423', '3254323']
newlist_2 = ['mipl-oldss','v1.0.2', 'deprecated','eelp234', 'deprecated']
newlist_3 = ['mipl-newss', 'new','v1.0.2','new', 'eelp234']
  

Я пытался написать что-то вроде:

 for items in list_1:
    for item in list_2: 
        if item[0] == items[0] and item[1] != items[1]:
             list_difference = [item[0], items[1], item[1], items[2], items[2]]
             newlist_1.append(list_difference)
        elif item[0] not in items[0]: 
             list_old_param = [item[0], item[1], 'deprecated', items[2], 'not-exist']
             newlist_2.append(list_old_param)
        elif items[0] not in item[0]:
             list_new_param = [item[0], 'new' , items[1], 'new', items[2]]
             newlist_3.append(list_new_param)
 
  

Кажется, что все данные добавляются и создают несколько записей из-за двух for циклов, так как же мне понять списки?

Вопросы: Как заставить его работать с добавлением только уникальных записей? Какие есть разумные способы написания кода для сравнения таких двух списков? Каковы самые простые способы? как гарантировать, что циклы не будут перегружать эти списки, поскольку списки будут продолжать меняться?

Ответ №1:

Другой способ сделать это — пробежаться по каждому списку по очереди, ища имена в другом списке. Вы можете получить прямой доступ, используя два dict s.

Моя функция ниже подготавливает данные, преобразуя списки в dicts и просматривая каждый dict из них и пытаясь получить доступ к имени в другом.

 list_1 = [
['mipl-abnd','v1.0.2','eelp234'],
['mipl-avfd','v1.1.5','32fv423'],
['mipl-awsd','v9.0.2','234eelp'],
['mipl-tgfd','v3.0.0','124fdge'],
['mipl-hrdss','v1.0.2','543rfd3'],
['mipl-oldss','v1.0.2','eelp234']] 


list_2 = [
['mipl-abnd','v1.0.2','eelp234'],
['mipl-avfd','v1.1.6','3254323'],
['mipl-awsd','v9.0.2','234eelp'],
['mipl-tgfd','v3.0.0','124fdge'],
['mipl-hrdss','v1.0.2','543rfd3'],
['mipl-newss','v1.0.2','eelp234']]

def compareLists(l1, l2):
    d1 = {k:[v1,v2] for k,v1,v2 in l1}
    d2 = {k:[v1,v2] for k,v1,v2 in l2}
    result = []
    for k,v in d2.items():
        if k in d1:
            v1 = d1[k]
            if v1[0] != v[0]:
                result.append([k,v1[0],v[0], v1[1],v[1]])
        else:
            result.append([k,'new',v[0],'new', v[1]])

    for k,v in d1.items():
        if k not in d2:
            result.append([k,v[0],'deprecated', v[1], 'deprecated'])
    
    return result

r = compareLists(list_1,list_2)
for d in r:
    print(d)
  

Выводите по мере необходимости.

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

1. Спасибо, это делает работу. Я никогда не играл с обоими списками и dicts вместе.