Wiem, jak uzyskać przecięcie dwóch płaskich list:
b1 = [1,2,3,4,5,9,11,15]
b2 = [4,5,6,7,8]
b3 = [val for val in b1 if val in b2]
lub
def intersect(a, b):
return list(set(a) & set(b))
print intersect(b1, b2)
Ale kiedy muszę znaleźć przecięcie list zagnieżdżonych, zaczynają się moje problemy:
c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]
c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]
Na koniec chciałbym otrzymać:
c3 = [[13,32],[7,13,28],[1,6]]
Czy możecie mi w tym pomóc?
Związane z
python
list
intersection
elfuego1
źródło
źródło
Odpowiedzi:
Jeśli chcesz:
Oto twoje rozwiązanie dla Python 2:
W Python 3
filter
zwraca iterowalną zamiastlist
, więc musisz zawijaćfilter
wywołanialist()
:Wyjaśnienie:
Część filtrująca bierze element każdej podlisty i sprawdza, czy znajduje się na liście źródeł c1. Zrozumienie listy jest wykonywane dla każdej podlisty w c2.
źródło
filter(set(c1).__contains__, sublist)
dla wydajności. btw, zaletą tego rozwiązania jest to, żefilter()
zachowuje typy łańcuchów i krotek.c3 = [[x for x in sublist if x in c1] for sublist in c2]
Nie musisz definiować skrzyżowania. To już pierwsza część zestawu.
źródło
set(b1) & set(b2)
? IMO jest odkurzaczem, aby móc korzystać z operatora.set
spowoduje szybszy kod o rząd wielkości. Oto przykładowy test porównawczy®: gist.github.com/andersonvom/4d7e551b4c0418de3160Dla osób, które chcą znaleźć przecięcie dwóch list, Pytający podał dwie metody:
Istnieje jednak metoda hybrydowa, która jest bardziej wydajna, ponieważ wystarczy wykonać tylko jedną konwersję między listą / zestawem, a nie trzema:
To będzie działać w O (n), podczas gdy jego oryginalna metoda obejmująca zrozumienie listy będzie działać w O (n ^ 2)
źródło
Podejście funkcjonalne:
i można go zastosować do bardziej ogólnego przypadku list 1+
źródło
set(*input_list[:1]).intersection(*input_list[1:])
. Wersja iterator (it = iter(input_list)
)reduce(set.intersection, it, set(next(it, [])))
. Obie wersje nie wymagają konwersji wszystkich list wejściowych do ustawienia. Ta ostatnia jest bardziej wydajna pod względem pamięci.from functools import reduce
aby użyć go w Pythonie 3. Lub jeszcze lepiej, użyj jawnejfor
pętli.Wersja z czystym listem
Wariant spłaszczenia:
Wariant zagnieżdżony:
źródło
Operator & przecina dwa zestawy.
źródło
Pytonicznym sposobem na przecięcie 2 list jest:
źródło
Powinieneś spłaszczyć używając tego kodu (wziętego z http://kogs-www.informatik.uni-hamburg.de/~meine/python_tricks ), kod nie został przetestowany, ale jestem pewien, że działa:
Po spłaszczeniu listy wykonujesz skrzyżowanie w zwykły sposób:
źródło
Od momentu
intersect
zdefiniowania wystarczy podstawowe zrozumienie listy:Poprawa dzięki uwadze S. Lott i powiązanej uwadze TM:
źródło
Dany:
Uważam, że następujący kod działa dobrze, a może bardziej zwięzły, jeśli używasz operacji set:
Ma:
W razie potrzeby:
mamy:
Nawiasem mówiąc, ten styl jest również w porządku dla bardziej pythonowego stylu:
źródło
Nie wiem, czy spóźnię się z odpowiedzią na twoje pytanie. Po przeczytaniu twojego pytania wymyśliłem funkcję intersect (), która może działać zarówno na liście, jak i na liście zagnieżdżonej. Użyłem rekurencji do zdefiniowania tej funkcji, jest ona bardzo intuicyjna. Mam nadzieję, że tego właśnie szukasz:
Przykład:
źródło
Czy rozważasz
[1,2]
przecięcie się[1, [2]]
? Czy to tylko liczby, na których Ci zależy, czy też struktura listy?Jeśli tylko liczby, sprawdź, jak „spłaszczyć” listy, a następnie użyj
set()
metody.źródło
Szukałem również sposobu, aby to zrobić, a ostatecznie skończyło się tak:
źródło
źródło
Możemy użyć do tego celu metod:
źródło
Aby zdefiniować przecięcie, które poprawnie uwzględnia liczność elementów, użyj
Counter
:źródło
Oto jeden ze sposobów ustawiania
c3
, który nie obejmuje zestawów:Ale jeśli wolisz użyć tylko jednej linii, możesz to zrobić:
Jest to zrozumienie listy w ramach rozumienia listy, co jest trochę niezwykłe, ale myślę, że nie powinieneś mieć większych problemów z przestrzeganiem tego.
źródło
Dla mnie jest to bardzo elegancki i szybki sposób na to :)
źródło
z
reduce
łatwością można sporządzić płaską listę .Wystarczy użyć inicjalizatora - trzeci argument w
reduce
funkcji.Powyższy kod działa zarówno dla python2, jak i python3, ale musisz zaimportować moduł zmniejsz jako
from functools import reduce
. Szczegółowe informacje znajdują się poniżej.dla python2
dla python3
źródło
Prosty sposób na znalezienie różnicy i przecięcia między iteracjami
Użyj tej metody, jeśli powtórzenie ma znaczenie
źródło