Liste in kleinere Listen aufteilen (in zwei Hälften teilen)

150

Ich suche nach einer Möglichkeit, eine Python-Liste einfach in zwei Hälften zu teilen.

Wenn ich also ein Array habe:

A = [0,1,2,3,4,5]

Ich würde bekommen können:

B = [0,1,2]

C = [3,4,5]
Corymathews
quelle

Antworten:

226
A = [1,2,3,4,5,6]
B = A[:len(A)//2]
C = A[len(A)//2:]

Wenn Sie eine Funktion wünschen:

def split_list(a_list):
    half = len(a_list)//2
    return a_list[:half], a_list[half:]

A = [1,2,3,4,5,6]
B, C = split_list(A)
Jason Coon
quelle
70
Sie müssen die int-Division in Python 3 erzwingen. // ist erforderlich.
Stefan Kendall
4
Gute Lösung, danke. Es funktioniert auch mit Brüchen wie 80/20 in Python3B = A[:(len(A) // 10) * 8] C = A[(len(A) // 10) * 8:]
Gergely M
87

Eine etwas allgemeinere Lösung (Sie können die Anzahl der gewünschten Teile angeben und nicht nur in zwei Hälften teilen):

BEARBEITEN : Der Beitrag wurde aktualisiert, um ungerade Listenlängen zu verarbeiten

EDIT2 : Aktualisiere den Beitrag erneut basierend auf Brians informativen Kommentaren

def split_list(alist, wanted_parts=1):
    length = len(alist)
    return [ alist[i*length // wanted_parts: (i+1)*length // wanted_parts] 
             for i in range(wanted_parts) ]

A = [0,1,2,3,4,5,6,7,8,9]

print split_list(A, wanted_parts=1)
print split_list(A, wanted_parts=2)
print split_list(A, wanted_parts=8)
ChristopheD
quelle
2
Wenn sich die Liste nicht gleichmäßig teilt (z. B. split_list ([1,2,3], 2)), werden tatsächlich want_parts + 1-Listen zurückgegeben.
Brian
3
Ein besserer Weg, denke ich, wäre: Länge = Länge (Alist); return [alist [i * Länge // gewollte Teile: (i + 1) * Länge // gewollte Teile] für i im Bereich (gewollte Teile)]. Auf diese Weise erhalten Sie eine möglichst gleichmäßige Verteilung und erhalten immer genau die gewünschten Teile (auch Pads mit [], wenn die gewünschten Teile> len (A))
Brian,
2
hi .. was bedeutet das symbol "//" ??
Frazman
2
@Fraz Es ist als Inline-Kommentar gemeint. Ignorieren Sie "// want_parts" und "// want_parts", damit das Skript ausgeführt wird.
PunjCoder
19
//bedeutet ganzzahlige Division. Sie sollten nicht ausgelassen werden, da sie für diese Arbeit sehr wichtig sind.
Alphadelta14
43
f = lambda A, n=3: [A[i:i+n] for i in range(0, len(A), n)]
f(A)

n - die vordefinierte Länge der Ergebnisarrays

Jaro
quelle
1
Dies funktioniert in meiner Situation hervorragend, fügt jedoch jeden zweiten Index jeder Liste in eine eigene Liste ein. Schwer zu erklären. Bitte antworten Sie, wenn Sie helfen können und ich werde mehr erklären.
Mike Issa
34
def split(arr, size):
     arrs = []
     while len(arr) > size:
         pice = arr[:size]
         arrs.append(pice)
         arr   = arr[size:]
     arrs.append(arr)
     return arrs

Prüfung:

x=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
print(split(x, 5))

Ergebnis:

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]
Siamand
quelle
1
auch nützlich, um Liste in Matrix zu konvertieren
mpgn
Das funktioniert, aber nicht ganz. Ich benutze diese Funktion in einer Schleife und die Längen variieren. Mit anderen Worten : for i,j in zip(list,lengths): print(split(i,j)). Die listund lengthsListen haben die gleiche Länge. j wechselt: 5,4,5,4,5, und die Aufteilungsfunktion arbeitet bei den ersten beiden Abwechslungen, dh sie teilt die erste ider Liste durch 5 und 4, ABER bei der nächsten Iteration teilt sie sie bei 4,4 auf. 1. : \ Bitte antworten Sie, wenn Sie möchten, dass ich mehr erkläre (eine neue Frage posten)
Mike Issa
15

Wenn Sie sich nicht für die Bestellung interessieren ...

def split(list):  
    return list[::2], list[1::2]

list[::2]Ruft jedes zweite Element in der Liste ab dem 0. Element ab.
list[1::2]Ruft jedes zweite Element in der Liste ab dem ersten Element ab.

sentythee
quelle
4
Sorgfältige Benennung des Args listdurch Abschatten des list(...)eingebauten Arg . Ich habe allgemein gesehen lstund list_verwendet, um es zu vermeiden.
Taylor Edmiston
3
das fühlt sich am pythonischsten an (ignoriert die falsche Benennung)
Tjorriemorrie
12

B,C=A[:len(A)/2],A[len(A)/2:]

John Montgomery
quelle
Ich denke, Sie haben die Teilung um 2 Schritte vergessen. :)
Stefan Kendall
11

Hier ist eine gängige Lösung, die arr in count part aufteilt

def split(arr, count):
     return [arr[i::count] for i in range(count)]
Chris Song
quelle
Dies verliert die Reihenfolge der Liste
Timmah
9
def splitter(A):
    B = A[0:len(A)//2]
    C = A[len(A)//2:]

 return (B,C)

Ich habe getestet, und der doppelte Schrägstrich ist erforderlich, um die int-Teilung in Python 3 zu erzwingen. Mein ursprünglicher Beitrag war korrekt, obwohl wysiwyg aus irgendeinem Grund in Opera pleite war.

Stefan Kendall
quelle
es behandelt nicht ungerade len (A) - haben Sie eine Lösung dafür?
N997
6

Es gibt ein offizielles Python-Rezept für den allgemeineren Fall der Aufteilung eines Arrays in kleinere Arrays mit einer Größe n.

from itertools import izip_longest
def grouper(n, iterable, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

Dieses Code-Snippet stammt von der Python-itertools-Dokumentseite .

Jonathan Berger
quelle
6

Mit Liste schneiden . Die Syntax ist grundsätzlichmy_list[start_index:end_index]

>>> i = [0,1,2,3,4,5]
>>> i[:3] # same as i[0:3] - grabs from first to third index (0->2)
[0, 1, 2]
>>> i[3:] # same as i[3:len(i)] - grabs from fourth index to end
[3, 4, 5]

Um die erste Hälfte der Liste zu erhalten, schneiden Sie vom ersten Index nach len(i)//2(wo //ist die Ganzzahldivision - also 3//2 will give the floored result of1 , instead of the invalid list index of1,5`):

>>> i[:len(i)//2]
[0, 1, 2]

..und tauschen Sie die Werte aus, um die zweite Hälfte zu erhalten:

>>> i[len(i)//2:]
[3, 4, 5]
dbr
quelle
was ist mit ungeraden len Listen)
N997
@ N997 Der Code sollte noch funktionieren; Sie haben nur eine unterschiedliche Anzahl von Elementen in jeder Liste. Nehmen wir also an, die Liste ist drei Elemente lang, der Divisionsoperator 3//2gibt das Ergebnis so aus 1, dass Sie das erhalten i[:1], was Sie erhalten [0]und i[1:]das gibt[1, 2]
dbr
3

Wenn Sie eine große Liste haben, ist es besser, itertools zu verwenden und eine Funktion zu schreiben, um jedes Teil nach Bedarf zu erhalten:

from itertools import islice

def make_chunks(data, SIZE):
    it = iter(data)
    # use `xragne` if you are in python 2.7:
    for i in range(0, len(data), SIZE):
        yield [k for k in islice(it, SIZE)]

Sie können dies wie folgt verwenden:

A = [0, 1, 2, 3, 4, 5, 6]

size = len(A) // 2

for sample in make_chunks(A, size):
    print(sample)

Die Ausgabe ist:

[0, 1, 2]
[3, 4, 5]
[6]

Vielen Dank an @thefourtheye und @Bede Constantinides

MA Heshmat Khah
quelle
3

10 Jahre später .. Ich dachte - warum nicht noch einen hinzufügen:

arr = 'Some random string' * 10; n = 4
print([arr[e:e+n] for e in range(0,len(arr),n)])
RoyM
quelle
2

Obwohl die obigen Antworten mehr oder weniger korrekt sind, können Probleme auftreten, wenn die Größe Ihres Arrays nicht durch 2 teilbar a / 2ist Geben Sie from __future__ import divisionam Anfang Ihres Skripts an. In jedem Fall ist es besser, sich für eine Ganzzahldivision zu entscheiden, dh a // 2um die "Vorwärts" -Kompatibilität Ihres Codes zu erreichen.

user91259
quelle
2

Dies ähnelt anderen Lösungen, ist jedoch etwas schneller.

# Usage: split_half([1,2,3,4,5]) Result: ([1, 2], [3, 4, 5])

def split_half(a):
    half = len(a) >> 1
    return a[:half], a[half:]
Ruslanas Balčiūnas
quelle
Cleverer Einsatz von Binärverschiebung!
Janusz Skonieczny
0

Mit Hinweisen von @ChristopheD

def line_split(N, K=1):
    length = len(N)
    return [N[i*length/K:(i+1)*length/K] for i in range(K)]

A = [0,1,2,3,4,5,6,7,8,9]
print line_split(A,1)
print line_split(A,2)
PunjCoder
quelle
0
#for python 3
    A = [0,1,2,3,4,5]
    l = len(A)/2
    B = A[:int(l)]
    C = A[int(l):]       
SuperGuy10
quelle
0

Eine weitere Sichtweise auf dieses Problem im Jahr 2020 ... Hier ist eine Verallgemeinerung des Problems. Ich interpretiere das 'Teilen einer Liste in zwei Hälften' als .. (dh nur zwei Listen und es darf kein Übergreifen auf ein drittes Array im Falle eines ungeraden Outs usw. geben). Wenn zum Beispiel die Array-Länge 19 ist und eine Division durch zwei mit dem Operator // 9 ergibt, erhalten wir zwei Arrays der Länge 9 und ein Array (Drittel) der Länge 1 (also insgesamt drei Arrays). Wenn wir möchten, dass eine allgemeine Lösung immer zwei Arrays ergibt, gehe ich davon aus, dass wir mit den resultierenden Duo-Arrays zufrieden sind, die nicht gleich lang sind (eines ist länger als das andere). Und dass davon ausgegangen wird, dass es in Ordnung ist, die Reihenfolge zu mischen (in diesem Fall abwechselnd).

"""
arrayinput --> is an array of length N that you wish to split 2 times
"""
ctr = 1 # lets initialize a counter

holder_1 = []
holder_2 = []

for i in range(len(arrayinput)): 

    if ctr == 1 :
        holder_1.append(arrayinput[i])
    elif ctr == 2: 
        holder_2.append(arrayinput[i])

    ctr += 1 

    if ctr > 2 : # if it exceeds 2 then we reset 
        ctr = 1 

Dieses Konzept funktioniert für eine beliebige Anzahl von Listenpartitionen, wie Sie möchten (Sie müssten den Code abhängig von der Anzahl der gewünschten Listenteile anpassen). Und ist ziemlich einfach zu interpretieren. Um die Dinge zu beschleunigen, können Sie diese Schleife sogar in Cython / C / C ++ schreiben, um die Dinge zu beschleunigen. Andererseits habe ich diesen Code in relativ kleinen Listen mit ~ 10.000 Zeilen ausprobiert und er endet in Sekundenbruchteilen.

Nur meine zwei Cent.

Vielen Dank!

Aaronlhe
quelle