Podziel listę na mniejsze listy (podziel na pół)

150

Szukam sposobu na łatwe podzielenie listy Pythona na pół.

Więc jeśli mam tablicę:

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

Byłbym w stanie uzyskać:

B = [0,1,2]

C = [3,4,5]
corymathews
źródło

Odpowiedzi:

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

Jeśli chcesz mieć funkcję:

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
źródło
70
Musisz wymusić dzielenie int w Pythonie 3. // jest wymagane.
Stefan Kendall
4
Niezłe rozwiązanie, dzięki. Działa również z ułamkami, takimi jak 80/20 w Pythonie3B = A[:(len(A) // 10) * 8] C = A[(len(A) // 10) * 8:]
Gergely M
87

Trochę bardziej ogólne rozwiązanie (możesz określić liczbę części, które chcesz, a nie tylko podzielić je na pół):

EDYCJA : zaktualizowany post do obsługi nieparzystych długości list

EDIT2 : ponownie zaktualizuj post na podstawie pouczających komentarzy Briana

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
źródło
2
Gdy lista nie dzieli się równo (np. Split_list ([1,2,3], 2)) to w rzeczywistości zwróci listę Want_parts + 1.
Brian
3
Myślę, że lepszym sposobem byłoby: length = len (alist); return [alist [i * length // poszukiwane_części: (i + 1) * długość // poszukiwane_części] for i in range (poszukiwane_części)]. W ten sposób uzyskujesz równomierną dystrybucję i zawsze otrzymujesz dokładnie elementy Want_parts (nawet pady z [] if Wanted_parts> len (A))
Brian
2
cześć… co oznacza symbol „//”?
frazman
2
@Fraz Jest to komentarz w tekście. Zignoruj ​​„// Want_parts” i „// Want_parts”, aby wykonać skrypt.
PunjCoder
19
//oznacza dzielenie liczb całkowitych. Nie należy ich pomijać, ponieważ są one niezbędne do wykonania tej pracy.
Alphadelta 14
43
f = lambda A, n=3: [A[i:i+n] for i in range(0, len(A), n)]
f(A)

n - predefiniowana długość tablic wynikowych

Jaro
źródło
1
Działa to świetnie w mojej sytuacji, jednak dodaje co drugi ostatni indeks z każdej listy do własnej listy. Trudno wytłumaczyć. Proszę o odpowiedź, jeśli możesz pomóc, a wyjaśnię więcej.
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

Test:

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

wynik:

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]
Siamand
źródło
1
przydatne również do konwersji listy do macierzy
mpgn
To działa, ale nie do końca. Używam tej funkcji w pętli, a długości są różne. Innymi słowy: for i,j in zip(list,lengths): print(split(i,j)). listI lengthswykazy mają taką samą długość. j jest naprzemiennie: 5,4,5,4,5, a funkcja split działa na dwóch pierwszych przemianach, tj. dzieli pierwszą iz listy na 5 i 4, ALE w następnej iteracji dzieli ją na 4,4, 1. : \ Proszę o odpowiedź, jeśli chcesz, żebym wyjaśnił więcej (opublikuj nowe pytanie)
Mike Issa
15

Jeśli nie zależy Ci na zamówieniu ...

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

list[::2]pobiera co drugi element listy, zaczynając od elementu zerowego.
list[1::2]pobiera co drugi element listy, zaczynając od pierwszego elementu.

sentythee
źródło
4
Ostrożnie nazywaj argument listz cieniowaniem list(...)wbudowanego. Widziałem lsti list_często używałem, aby tego uniknąć.
Taylor Edmiston
3
to wydaje się najbardziej pythonowe (ignorując nieprawidłowe nazewnictwo)
Tjorriemorrie
12

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

John Montgomery
źródło
Myślę, że zapomniałeś o dzieleniu przez 2 kroki. :)
Stefan Kendall
11

Oto powszechne rozwiązanie, podzielone na część licznikową

def split(arr, count):
     return [arr[i::count] for i in range(count)]
Chris Song
źródło
To traci kolejność na liście
Timmah
9
def splitter(A):
    B = A[0:len(A)//2]
    C = A[len(A)//2:]

 return (B,C)

Testowałem i podwójny ukośnik jest wymagany do wymuszenia dzielenia int w Pythonie 3. Mój oryginalny post był poprawny, chociaż z jakiegoś powodu wysiwyg zepsuł się w Operze.

Stefan Kendall
źródło
nie obsługuje dziwnego len (A) - czy masz na to rozwiązanie?
N997
6

Istnieje oficjalna recepta na Pythona dla bardziej uogólnionego przypadku podziału tablicy na mniejsze tablice o rozmiarze 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)

Ten fragment kodu pochodzi ze strony dokumentacji python itertools .

Jonathan Berger
źródło
6

Korzystanie z wycinania list . W zasadzie składniamy_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]

Aby uzyskać pierwszą połowę listy, wycinamy od pierwszego indeksu do len(i)//2(gdzie //jest dzielenie liczby całkowitej - czyli 3//2 will give the floored result of1 , instead of the invalid list index of1,5`):

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

.. i zamień wartości wokół, aby uzyskać drugą połowę:

>>> i[len(i)//2:]
[3, 4, 5]
dbr
źródło
co z nieparzystymi listami
lenów
@ N997 Kod powinien nadal działać; po prostu otrzymujesz różną liczbę pozycji na każdej liście. Powiedzmy, że lista jest długa na trzy elementy, operator dzielenia 3//2daje wynik tak 1, że otrzymujesz, i[:1]który daje [0]i i[1:]który daje[1, 2]
dbr
3

Jeśli masz dużą listę, lepiej użyć itertools i napisać funkcję, aby uzyskać każdą część w razie potrzeby:

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)]

Możesz użyć tego jak:

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

size = len(A) // 2

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

Wynik to:

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

Podziękowania dla @thefourtheye i @Bede Constantinides

MA Heshmat Khah
źródło
3

10 lat później ... pomyślałem - czemu nie dodać kolejnego:

arr = 'Some random string' * 10; n = 4
print([arr[e:e+n] for e in range(0,len(arr),n)])
RoyM
źródło
2

Chociaż powyższe odpowiedzi są mniej więcej poprawne, możesz napotkać kłopoty, jeśli rozmiar twojej tablicy nie jest podzielny przez 2, w wyniku tego a / 2, że jest nieparzystą, jest zmiennoprzecinkową w Pythonie 3.0, a we wcześniejszej wersji, jeśli określić from __future__ import divisionna początku skryptu. W każdym razie lepiej jest wybrać dzielenie całkowitoliczbowe, tj. a // 2W celu uzyskania zgodności kodu "do przodu".

user91259
źródło
2

Jest to podobne do innych rozwiązań, ale trochę szybsze.

# 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
źródło
Sprytne wykorzystanie binarnej zmiany biegów!
Janusz Skonieczny
0

Z podpowiedziami @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
źródło
0
#for python 3
    A = [0,1,2,3,4,5]
    l = len(A)/2
    B = A[:int(l)]
    C = A[int(l):]       
SuperGuy10
źródło
0

Inne podejście do tego problemu w 2020 roku ... Oto uogólnienie problemu. Interpretuję „podziel listę na pół” jako… (tj. Tylko dwie listy i nie będzie żadnego efektu przeniesienia na trzecią tablicę w przypadku nieparzystej listy itp.). Na przykład, jeśli długość tablicy wynosi 19, a dzielenie przez dwa za pomocą operatora // daje 9, a otrzymamy dwie tablice o długości 9 i jedną (trzecią) o długości 1 (czyli w sumie trzy tablice). Jeśli chcielibyśmy, aby ogólne rozwiązanie dawało dwie tablice przez cały czas, zakładam, że jesteśmy zadowoleni z wynikowych tablic duet, które nie mają równej długości (jedna będzie dłuższa od drugiej). I że założono, że mieszanie zamówienia (naprzemiennie w tym przypadku) jest w porządku.

"""
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 

Ta koncepcja działa dla dowolnej ilości partycji listy, jak chcesz (musiałbyś dostosować kod w zależności od tego, ile części listy chcesz). I jest raczej łatwy do interpretacji. Aby przyspieszyć działanie, możesz nawet napisać tę pętlę w cython / C / C ++, aby przyspieszyć działanie. Z drugiej strony wypróbowałem ten kod na stosunkowo małych listach ~ 10000 wierszy i kończy się w ułamku sekundy.

Tylko moje dwa centy.

Dzięki!

aaronlhe
źródło