funktioniert nur, wenn l1 und l2 die gleiche Anzahl von Elementen haben
Emmanuel
14
@ Emmanuel: Die Frage lautet: "Gibt es in Python eine gute Möglichkeit, zwei Listen gleicher Länge zu verschachteln ?"
NPE
1
Wenn Sie zur längsten Liste izip_longestauffüllen zip_longestmö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']
>>> 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 + bwird 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 aund b: Die erste Zeile ordnet die Elemente von aallen geradzahligen Indizes von zu c; Der zweite ordnet die Elemente von ballen ungeradzahligen Indizes von zu c.
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> [y for x in map(None,l1,l2) for y in x if y isnotNone]
[1, 10, 2, 20, 3, 30]
Dies funktioniert, weil Map parallel auf Listen arbeitet. Es funktioniert genauso unter 2.2. Mit Noneden aufgerufenen Funktionen mapwird eine Liste von Tupeln erstellt:
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 innotNone]
[1, 10, 101, 2, 20, 102, 3, 30, 103, 104]
if ywird auch herausfiltern 0, if y is not Noneist weniger zerbrechlich.
Jochen Ritzel
@Jochen Ritzel: Danke! Ich stimme mit Ihnen ein. Fest. Ich schrieb es nur mit Muskeln beschäftigt ...
der Wolf
3
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]
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
definterleave(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
it = iter(l1); list((yield next(it)) or i for i in l2)
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
undl2
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]
quelle
izip_longest
auffüllenzip_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 Verschachtelunga
undb
: Die erste Zeile ordnet die Elemente vona
allen geradzahligen Indizes von zuc
; Der zweite ordnet die Elemente vonb
allen ungeradzahligen Indizes von zuc
.quelle
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 erhaltenzip
:import itertools list(itertools.chain(*zip(a, b))) # [1, 10, 2, 20, 3, 30]
Alternativen
itertools.zip_longest
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]
more_itertools
+Eine Bibliothek, die mit dem
roundrobin
Rezept itertools geliefert wird,interleave
undinterleave_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 mit
pip install more_itertools
quelle
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']
quelle
roundrobin
Rezept aus demitertools
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 Funktionenmap
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]
quelle
if y
wird auch herausfiltern0
,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]
quelle
[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 behaltenquelle
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]
quelle
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]
quelle