Как сравнить список списков/наборов в python?
Что является самым простым способом сравнения 2 списков/наборов и вывода различий? Есть ли встроенные функции, которые помогут мне сравнить вложенные списки/наборы?
Входы:
First_list = [['Test.doc', '1a1a1a', 1111],
['Test2.doc', '2b2b2b', 2222],
['Test3.doc', '3c3c3c', 3333]
]
Secnd_list = [['Test.doc', '1a1a1a', 1111],
['Test2.doc', '2b2b2b', 2222],
['Test3.doc', '8p8p8p', 9999],
['Test4.doc', '4d4d4d', 4444]]
Ожидаемый результат:
Differences = [['Test3.doc', '3c3c3c', 3333],
['Test3.doc', '8p8p8p', 9999],
['Test4.doc', '4d4d4d', 4444]]
Ответы
Ответ 1
Итак, вам нужна разница между двумя списками элементов.
first_list = [['Test.doc', '1a1a1a', 1111],
['Test2.doc', '2b2b2b', 2222],
['Test3.doc', '3c3c3c', 3333]]
secnd_list = [['Test.doc', '1a1a1a', 1111],
['Test2.doc', '2b2b2b', 2222],
['Test3.doc', '8p8p8p', 9999],
['Test4.doc', '4d4d4d', 4444]]
Сначала я перечислил список списков в список кортежей, так как кортежи хешируются (списки отсутствуют), поэтому вы можете преобразовать список кортежей в набор кортежей:
first_tuple_list = [tuple(lst) for lst in first_list]
secnd_tuple_list = [tuple(lst) for lst in secnd_list]
Затем вы можете создавать наборы:
first_set = set(first_tuple_list)
secnd_set = set(secnd_tuple_list)
EDIT (предложенный sdolan): Вы могли бы сделать последние два шага для каждого списка в одном слое:
first_set = set(map(tuple, first_list))
secnd_set = set(map(tuple, secnd_list))
Примечание: map
- это команда функционального программирования, которая применяет функцию в первом аргументе (в данном случае к функции tuple
) к каждому элементу во втором аргументе (который в нашем случае представляет собой список списков).
и найти симметричную разницу между множествами:
>>> first_set.symmetric_difference(secnd_set)
set([('Test3.doc', '3c3c3c', 3333),
('Test3.doc', '8p8p8p', 9999),
('Test4.doc', '4d4d4d', 4444)])
Примечание first_set ^ secnd_set
эквивалентно symmetric_difference
.
Также, если вы не хотите использовать наборы (например, используя python 2.2), его довольно просто сделать. Например, со списком:
>>> [x for x in first_list if x not in secnd_list] + [x for x in secnd_list if x not in first_list]
[['Test3.doc', '3c3c3c', 3333],
['Test3.doc', '8p8p8p', 9999],
['Test4.doc', '4d4d4d', 4444]]
или с функциональной командой filter
и lambda
. (Вы должны проверить оба пути и объединить).
>>> filter(lambda x: x not in secnd_list, first_list) + filter(lambda x: x not in first_list, secnd_list)
[['Test3.doc', '3c3c3c', 3333],
['Test3.doc', '8p8p8p', 9999],
['Test4.doc', '4d4d4d', 4444]]
Ответ 2
Не уверен, что для этого есть хорошая функция, но "ручной" способ сделать это не сложно:
differences = []
for list in firstList:
if list not in secondList:
differences.append(list)
Ответ 3
>>> First_list = [['Test.doc', '1a1a1a', '1111'], ['Test2.doc', '2b2b2b', '2222'], ['Test3.doc', '3c3c3c', '3333']]
>>> Secnd_list = [['Test.doc', '1a1a1a', '1111'], ['Test2.doc', '2b2b2b', '2222'], ['Test3.doc', '3c3c3c', '3333'], ['Test4.doc', '4d4d4d', '4444']]
>>> z = [tuple(y) for y in First_list]
>>> z
[('Test.doc', '1a1a1a', '1111'), ('Test2.doc', '2b2b2b', '2222'), ('Test3.doc', '3c3c3c', '3333')]
>>> x = [tuple(y) for y in Secnd_list]
>>> x
[('Test.doc', '1a1a1a', '1111'), ('Test2.doc', '2b2b2b', '2222'), ('Test3.doc', '3c3c3c', '3333'), ('Test4.doc', '4d4d4d', '4444')]
>>> set(x) - set(z)
set([('Test4.doc', '4d4d4d', '4444')])
Ответ 4
Я думаю, вам придется конвертировать списки в настройки:
>>> a = {('a', 'b'), ('c', 'd'), ('e', 'f')}
>>> b = {('a', 'b'), ('h', 'g')}
>>> a.symmetric_difference(b)
{('e', 'f'), ('h', 'g'), ('c', 'd')}
Ответ 5
http://docs.python.org/library/difflib.html является хорошим отправным местом для того, что вы ищете.
Если вы примените его рекурсивно к дельтам, вы сможете обрабатывать вложенные структуры данных. Но это займет определенную работу.
Ответ 6
Используя множество понятий, вы можете сделать его однострочным. Если вы хотите:
чтобы получить набор кортежей, тогда:
Differences = {tuple(i) for i in First_list} ^ {tuple(i) for i in Secnd_list}
Или получить список кортежей, затем:
Differences = list({tuple(i) for i in First_list} ^ {tuple(i) for i in Secnd_list})
Или получить список списков (если вы действительно хотите), то:
Differences = [list(j) for j in {tuple(i) for i in First_list} ^ {tuple(i) for i in Secnd_list}]
PS: Я читаю здесь: fooobar.com/info/17721/..., что функция map() не является питоническим способом делать что-то.