2016-01-30 25 views
5

Oto moje dwie listy;Python - Przecięcie dwóch list list

k = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,9]] 
kDash = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,6], [1,2]] 

Moje wyniki powinny być następujące;

jak mogę dostać się do tego wyjścia?

góry dziękuję

+0

problem I stwierdzono, że niezdolność do przekształcania listę list do zestawu, jeśli to było możliwe, to skrzyżowanie może być podjęta łatwo –

+0

proszę wyjaśnić logikę, według której uzyskano dane wyjściowe. – timgeb

+0

Czy możesz wyjaśnić, dlaczego '[5, 6]' i '[5, 9]' znajdują się na skrzyżowaniu? – NiziL

Odpowiedz

4

Trzeba będzie konwertować list do listy krotek, a następnie użyj skrzyżowanie. Zauważ, że poniższe rozwiązanie może zawierać elementy w innej kolejności, a duplikaty oczywiście nie będą dostępne, ponieważ używam zestawu.

In [1]: l1 = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,9]] 

In [2]: l2 = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,6], [1,2]] 

In [3]: [list(x) for x in set(tuple(x) for x in l1).intersection(set(tuple(x) for x in l2))] 
Out[3]: [[1, 2], [5, 6, 2], [3], [4]] 

alternatywnie można zapisać skrzyżowanie w zmiennej i uzyskać ostateczną listę, jeśli zamówienie, duplikaty są konieczne:

In [4]: intersection = set(tuple(x) for x in l1).intersection(set(tuple(x) for x in l2)) 

In [5]: [x for x in l1 if tuple(x) in intersection] 
Out[5]: [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4]] 

A skrzyżowanie, na wszelki wypadek, jeśli jesteś zainteresowany.

In [6]: print intersection 
set([(1, 2), (5, 6, 2), (3,), (4,)]) 

Będzie to działać całkiem dobrze dla dużych list, ale wówczas, gdy listy są małe, należy zbadać inne rozwiązania w drodze @timegb (którego rozwiązanie będzie bardzo unoptimal dłuższych list)

3

Ponieważ listy wyjściowej ma zduplikowane elementy, tak naprawdę nie potrzebujesz klasycznego skrzyżowania. Podstawowe zrozumienie listy zrobi wszystko.

>>> k = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,9]] 
>>> kDash = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4], [5,6], [1,2]] 
>>> [x for x in k if x in kDash] 
[[1, 2], [4], [5, 6, 2], [1, 2], [3], [4]] 

Dla dużych list, chcemy uzyskać czas potrzebny zadzwonić __contains__ O (1) zamiast O (n):

>>> stuff_in_kDash = set(map(tuple, kDash)) 
>>> [x for x in k if tuple(x) in stuff_in_kDash] 
[[1, 2], [4], [5, 6, 2], [1, 2], [3], [4]] 
+0

A jeśli chcesz usunąć duplikat elementu, możesz rzucić okiem na [tę odpowiedź] (http://stackoverflow.com/questions/2213923/python-removing-duplicates -from-a-list-of-list);) – NiziL

+1

To będzie * lot * wolniejszy niż metody skrzyżowania 'set'. Skalowanie to coś w rodzaju 'O (n²k)' gdzie 'n' to liczba podlisty, a' k' to średnia długość każdej podlisty. – Veedrac

+0

Właśnie zdałem sobie sprawę, że lista wyjściowa programów operacyjnych zawiera zduplikowane elementy. Tak więc kompilacja listy jest drogą do wyjścia, chyba że specyfikacje ulegną zmianie. – timgeb

2

Czystsze sposób pisać skrzyżowanie jest

{tuple(x) for x in l1} & {tuple(x) for x in l2} 

dobrą alternatywą jest

{tuple(x) for x in l1}.intersection(map(tuple, l2)) 
0

Choć co zostało tutaj napisane jest o wiele bardziej eleganckie rozwiązania, oto kolejna

def foo(L1,L2): 
    res=[] 
    for lst in L1: 
     if lst in L2: 
      res.append(lst) 
    return res