Czy w Pythonie istnieje dobry sposób na przeplatanie dwóch list o tej samej długości?Przeplatanie dwóch list w Pythonie
Powiedz, że dostałem [1,2,3]
i [10,20,30]
. Chciałbym przekształcić te w [1,10,2,20,3,30]
.
Czy w Pythonie istnieje dobry sposób na przeplatanie dwóch list o tej samej długości?Przeplatanie dwóch list w Pythonie
Powiedz, że dostałem [1,2,3]
i [10,20,30]
. Chciałbym przekształcić te w [1,10,2,20,3,30]
.
Po zaksięgowaniu pytanie, zdałem sobie sprawę, że mogę po prostu wykonaj następujące czynności:
[val for pair in zip(l1, l2) for val in pair]
gdzie l1
i l2
są dwie listy.
Najbardziej lubię rozwiązanie aix. Oto inny sposób myślę powinny działać w 2.2:
>>> x=range(3)
>>> x
[0, 1, 2]
>>> y=range(7,10)
>>> y
[7, 8, 9]
>>> sum(zip(x,y),[])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "tuple") to list
>>> sum(map(list,zip(x,y)),[])
[0, 7, 1, 8, 2, 9]
i jeszcze jeden sposób:
>>> a=[x,y]
>>> [a[i][j] for j in range(3) for i in (0,1)]
[0, 7, 1, 8, 2, 9]
oraz:
>>> sum((list(i) for i in zip(x,y)),[])
[0, 7, 1, 8, 2, 9]
alternatywne:
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> [y for x in map(None,l1,l2) for y in x if y is not None]
[1, 10, 2, 20, 3, 30]
to działa ponieważ map działa równolegle na listach. To works the same zgodnie z 2.2. Sama z None
co zwanych funkcjami map
tworzy listę krotek:
>>> map(None,l1,l2,'abcd')
[(1, 10, 'a'), (2, 20, 'b'), (3, 30, 'c'), (None, None, 'd')]
Następnie wystarczy spłaszczyć listę krotek.
Zaletą oczywiście jest map
będzie pracować dla dowolnej liczby list i będzie działać, nawet jeśli są one różne długości:
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> l3=[101,102,103,104]
>>> [y for x in map(None,l1,l2,l3) for y in x if y in not None]
[1, 10, 101, 2, 20, 102, 3, 30, 103, 104]
'jeśli y' odfiltruje również "0", "jeśli y nie jest żadnym" jest mniej kruche. –
@Jochen Ritzel: Dzięki! Zgadzam się z Tobą. Naprawiony. Napisałem go tylko z zaangażowanymi mięśniami ... –
dla Pythona> = 2.3, istnieje extended slice syntax:
>>> a = [0, 2, 4, 6, 8]
>>> b = [1, 3, 5, 7, 9]
>>> c = a + b
>>> c[::2] = a
>>> c[1::2] = b
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Linia c = a + b
służy jako prosty sposób utworzenia nowej listy o dokładnie odpowiedniej długości (na tym etapie jej zawartość nie jest ważna). Następne dwa wiersze odpowiadają faktycznej pracy przeplatania a
i b
: pierwsza przypisuje elementy a
do wszystkich indeksów parzystych o numerach c
; drugi przypisuje elementy b
do wszystkich nieparzystych indeksów c
.
Potrzebowałem sposobu, aby to zrobić z listami o różnych rozmiarach, których akceptowana odpowiedź nie dotyczy.
Moje rozwiązanie używa generatora i jego użycie wygląda nieco ładniej z tego powodu:
def interleave(l1, l2):
iter1 = iter(l1)
iter2 = iter(l2)
while True:
try:
if iter1 != None:
yield next(iter1)
except StopIteration:
iter1 = None
try:
if iter2 != None:
yield next(iter2)
except StopIteration:
iter2 = None
if iter1 == None and iter2 == None:
raise StopIteration()
i jego wykorzystania:
>>> a = [1, 2, 3, 4, 5]
>>> b = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list(interleave(a, b))
[1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 'e', 'f', 'g']
>>> list(interleave(b, a))
['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f', 'g']
Istnieje kilka opcji.
# Given
a = [1, 2, 3]
b = [10, 20, 30]
Można uzyskać listę przeplatanych z itertools
:
import itertools
list(itertools.chain(*zip(a, b)))
# [1, 10, 2, 20, 3, 30]
Rozważ zainstalowanie more_itertools
- biblioteka, która jest dostarczana z implementacjami interleave
, interleave_longest
i roundrobin
itertools recipe.
import more_itertools
list(more_itertools.interleave(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.roundrobin(a, b))
# [1, 10, 2, 20, 3, 30]
Wreszcie coś ciekawego, w Pythonie 3:
list(filter(None, ((yield from i) for i in zip(a, b))))
# [1, 10, 2, 20, 3, 30]
[el for el in itertools.chain(*itertools.izip_longest([1,2,3], [4,5])) if el is not None]
Dopóki nie masz None
że chcesz zachować
Zdajesz sobie sprawę, że 2.2 jest teraz masz dziesięć lat? Nie ma powodu, aby nadal go używać. –
@ DanielRoseman: Tak. W tym przypadku nie mam wyboru. – NPE
Niezalecane, ale spróbuj tego: 'it = iter (l1); list ((yield next (it)) lub i for for l2) ' –