Gibt es in Python eine gute Möglichkeit, zwei Listen gleicher Länge zu verschachteln?
Sagen Sie, ich bin gegeben [1,2,3]
und [10,20,30]
. Ich würde diese gerne in verwandeln [1,10,2,20,3,30]
.
Antworten:
Nachdem ich die Frage gestellt habe, habe ich festgestellt, dass ich einfach Folgendes tun kann:
[val for pair in zip(l1, l2) for val in pair]
wo l1
und l2
sind die beiden Listen.
Wenn N Listen verschachtelt werden müssen, dann
lists = [l1, l2, ...]
[val for tup in zip(*lists) for val in tup]
izip_longest
auffüllen zip_longest
möchten , verwenden Sie für python2 und für python3 `Ergebnisse [val for pair in itertools.zip_longest(l1, l2) for val in pair]
mit['a', 'b', 'a', 'b', 'a', 'b', None, 'b', None, 'b', None, 'b']
Für Python> = 2.3 gibt es eine erweiterte 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]
Die Zeile c = a + b
wird auf einfache Weise verwendet, um eine neue Liste mit genau der richtigen Länge zu erstellen (in diesem Stadium ist der Inhalt nicht wichtig). Die nächsten beiden Zeilen erledigen die eigentliche Arbeit der Verschachtelung a
und b
: Die erste Zeile ordnet die Elemente von a
allen geradzahligen Indizes von zu c
; Der zweite ordnet die Elemente von b
allen ungeradzahligen Indizes von zu c
.
Gegeben
a = [1, 2, 3]
b = [10, 20, 30]
c = [100, 200, 300, 999]
Code
Unter der Annahme von Listen gleicher Länge können Sie eine verschachtelte Liste mit itertools.chain
und erhalten zip
:
import itertools
list(itertools.chain(*zip(a, b)))
# [1, 10, 2, 20, 3, 30]
Alternativen
Allgemeiner bei ungleichen Listen verwenden zip_longest
(empfohlen):
[x for x in itertools.chain(*itertools.zip_longest(a, c)) if x is not None]
# [1, 100, 2, 200, 3, 300, 999]
Viele Listen können sicher verschachtelt werden:
[x for x in itertools.chain(*itertools.zip_longest(a, b, c)) if x is not None]
# [1, 10, 100, 2, 20, 200, 3, 30, 300, 999]
Eine Bibliothek, die mit dem roundrobin
Rezept itertools geliefert wird, interleave
und interleave_longest
.
import more_itertools
list(more_itertools.roundrobin(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave_longest(a, c))
# [1, 100, 2, 200, 3, 300, 999]
yield from
Zum Schluss noch etwas Interessantes in Python 3 (obwohl nicht empfohlen):
list(filter(None, ((yield from x) for x in zip(a, b))))
# [1, 10, 2, 20, 3, 30]
list([(yield from x) for x in zip(a, b)])
# [1, 10, 2, 20, 3, 30]
+ Installieren mitpip install more_itertools
Ich brauchte einen Weg, dies mit Listen unterschiedlicher Größe zu tun, die in der akzeptierten Antwort nicht angesprochen werden.
Meine Lösung verwendet einen Generator und seine Verwendung sieht deshalb etwas besser aus:
def interleave(l1, l2):
iter1 = iter(l1)
iter2 = iter(l2)
while True:
try:
if iter1 is not None:
yield next(iter1)
except StopIteration:
iter1 = None
try:
if iter2 is not None:
yield next(iter2)
except StopIteration:
iter2 = None
if iter1 is None and iter2 is None:
raise StopIteration()
Und seine Verwendung:
>>> 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']
roundrobin
Rezept aus dem itertools
Modul ist eine allgemeinere Erweiterung davon.
Alternative:
>>> 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]
Dies funktioniert, weil Map parallel auf Listen arbeitet. Es funktioniert genauso unter 2.2. Mit None
den aufgerufenen Funktionen map
wird eine Liste von Tupeln erstellt:
>>> map(None,l1,l2,'abcd')
[(1, 10, 'a'), (2, 20, 'b'), (3, 30, 'c'), (None, None, 'd')]
Dann reduzieren Sie einfach die Liste der Tupel.
Der Vorteil ist natürlich, dass es map
für eine beliebige Anzahl von Listen funktioniert und auch dann, wenn sie unterschiedlich lang sind:
>>> 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]
if y
wird auch herausfiltern 0
, if y is not None
ist weniger zerbrechlich.
Die Lösung von aix gefällt mir am besten. Hier ist eine andere Möglichkeit, die meiner Meinung nach in 2.2 funktionieren sollte:
>>> 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]
und noch ein Weg:
>>> a=[x,y]
>>> [a[i][j] for j in range(3) for i in (0,1)]
[0, 7, 1, 8, 2, 9]
und:
>>> sum((list(i) for i in zip(x,y)),[])
[0, 7, 1, 8, 2, 9]
[el for el in itertools.chain(*itertools.izip_longest([1,2,3], [4,5])) if el is not None]
Solange du das nicht hast None
, willst du es behalten
Um den Titel der Frage "Verschachteln Sie mehrere Listen gleicher Länge in Python" zu beantworten, können Sie die 2-Listen-Antwort von @ekhumoro verallgemeinern. Dies erfordert ausdrücklich, dass die Listen im Gegensatz zur (eleganten) Lösung von @NPE dieselbe Länge haben
import itertools
def interleave(lists):
"""Interleave a list of lists.
:param lists: List of lists; each inner length must be the same length.
:returns: interleaved single list
:rtype: list
"""
if len(set(len(_) for _ in lists)) > 1:
raise ValueError("Lists are not all the same length!")
joint = list(itertools.chain(*lists))
for l_idx, li in enumerate(lists):
joint[l_idx::len(lists)] = li
return joint
Beispiele:
>>> interleave([[0,2,4], [1, 3, 5]])
[0, 1, 2, 3, 4, 5]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12]])
[0, 1, 10, 2, 3, 11, 4, 5, 12]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14, 15]])
[0, 1, 10, 13, 2, 3, 11, 14, 4, 5, 12, 15]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in interleave
ValueError: Lists are not all the same length!
>>> interleave([[0,2,4]])
[0, 2, 4]
Zu spät zur Party, und es gibt viele gute Antworten, aber ich möchte auch eine einfache Lösung mit der extend()
Methode anbieten:
list1 = [1, 2, 3]
list2 = [10, 20, 30]
new_list = []
for i in range(len(list1)):
new_list.extend([list1[i], list2[i]])
print(new_list)
Ausgabe:
[1, 10, 2, 20, 3, 30]
it = iter(l1); list((yield next(it)) or i for i in l2)