2010-01-08 8 views
2

У меня есть два вложенных списков, каждый вложенный список, содержащий две строки т.д .:Сравнение Python вложенные списки

list 1 [('EFG', '[3,4,5]'), ('DEF', '[2,3,4]')] and list 2 [('DEF', '[2,3,4]'), ('FGH', '[4,5,6]')] 

Я хотел бы сравнить два списка и восстановить эти вложенные списки, которые идентичны друг другу. В этом случае будет возвращено только ('DEF','[2,3,4]'). Списки могут затянуться. Есть ли эффективный способ сделать это?

ответ

8

Если списки содержат только строки кортежи, то самый простой способ сделать это с помощью множества пересечение (&):

>>> set([('EFG', '[3,4,5]'), ('DEF', '[2,3,4]')]) & set([('DEF', '[2,3,4]'), ('FGH', '[4,5,6]')]) 
set([('DEF', '[2,3,4]')]) 
0

Вот один подход. Преобразуйте свои списки в группы и найдите их перекрестки.

>>> a,b = set([('EFG', '[3,4,5]'), ('DEF', '[2,3,4]')]), set([('DEF', '[2,3,4]'), ('FGH', '[4,5,6]')]) 
>>> print a.intersection(b) 
set([('DEF', '[2,3,4]')]) 

Я не думаю, что это сильно ухудшит вашу длину списков.

0

Просто используйте установить встроенные функции для наборов

def get_set(list1,list2): 
    s = set(list1) 
    s &= set(list2) 
    return s 

И Boom есть ваш союз

+1

союз? Разве вы не имеете в виду * перекресток *? –

0
intersection = [item for item in list1 if item in list2] 

Но использовать его только, если по какой-то причине у вас есть mutables в списках и не может преобразовать в набор. Конечно, все зависит от размера ваших списков и количества дубликатов, но это может быть в 10 раз медленнее.

+1

Это, как правило, будет дороже, чем набор решений. – Brian

+0

Да. Увидеть это сейчас. Это показатель 10 в моих тестах. – Debilski

+0

Однако это будет работать, если типы, содержащиеся в списке, не являются хешируемыми, тогда как все решения на основе набора не будут выполнены. –

3

Использование наборов, чтобы сделать это очень хорошая реализация, но для оптимальной работы следует использовать только один набор:

set1 = set([('EFG', '[3,4,5]'), ('DEF', '[2,3,4]')]) 
matches = [x for x in [('DEF', '[2,3,4]'), ('FGH', '[4,5,6]')] if x in set1] 
+0

Не могли бы вы объяснить, почему это лучше? –

+0

Создание набора из последовательности требует итерации через него, поэтому для генерации обоих наборов требуется итерация через обе последовательности. Кроме того, выполнение пересечения между двумя наборами требует итерации через один из них и выполнения операции членства с другой. Поэтому, превращая их как в последовательности, так и пересекающиеся, необходимо повторить одну последовательность один раз, а другую - дважды. Решение, которое я предоставил, конвертирует только один из списков, а затем выполняет итерацию через другую, сохраняя одно итерационное число. –

+1

Если список -> набор преобразований и заданное пересечение происходит в C++, а не python, это может быть быстрее. – tgray

Смежные вопросы