Membagi daftar menjadi daftar yang lebih kecil (terbagi dua)


150

Saya mencari cara untuk dengan mudah membagi daftar python menjadi dua.

Sehingga jika saya memiliki sebuah array:

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

Saya bisa mendapatkan:

B = [0,1,2]

C = [3,4,5]

Jawaban:


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

Jika Anda ingin fungsi:

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)

70
Anda perlu memaksa divisi int dalam Python 3. // diperlukan.
Stefan Kendall

4
Solusi yang bagus, terima kasih. Ini juga bekerja dengan fraksi seperti 80/20 di Python3B = A[:(len(A) // 10) * 8] C = A[(len(A) // 10) * 8:]
Gergely M

87

Solusi yang sedikit lebih umum (Anda dapat menentukan jumlah bagian yang Anda inginkan, bukan hanya membagi 'dua'):

Sunting : posting yang diperbarui untuk menangani panjang daftar ganjil

EDIT2 : perbarui posting lagi berdasarkan komentar informatif Brians

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)

2
Ketika daftar tidak dibagi secara merata (mis. Split_list ([1,2,3], 2)) ini sebenarnya akan mengembalikan daftar Want_parts +1.
Brian

3
Cara yang lebih baik menurut saya adalah: length = len (alist); return [alist [i * length // wanted_parts: (i + 1) * length // wanted_parts] untuk i dalam range (wanted_parts)]. Dengan cara itu Anda mendapatkan distribusi yang merata, dan selalu mendapatkan item yang diinginkan dengan tepat (bagian dengan pad [] jika ingin_part> len (A))
Brian

2
hai .. apa arti simbol "//" ??
frazman

2
@Fraz Ini dimaksudkan sebagai komentar inline. Abaikan "// wanted_parts" dan "// wanted_parts" untuk membuat skrip dieksekusi.
PunjCoder

19
//berarti pembagian bilangan bulat. Mereka tidak boleh ditinggalkan karena mereka sangat penting dalam membuat pekerjaan ini.
Alphadelta14

43
f = lambda A, n=3: [A[i:i+n] for i in range(0, len(A), n)]
f(A)

n - panjang array hasil yang telah ditentukan


1
Ini berfungsi baik dalam situasi saya, tetapi menambahkan setiap indeks terakhir lainnya dari setiap daftar ke dalam daftar itu sendiri. Sulit untuk dijelaskan. Harap balas jika Anda dapat membantu dan saya akan menjelaskan lebih lanjut.
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

Uji:

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

hasil:

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]

1
juga berguna untuk mengubah daftar menjadi matriks
mpgn

Ini bekerja, tetapi tidak cukup. Saya menggunakan fungsi ini dalam satu lingkaran, dan panjangnya bervariasi. Dengan kata lain: for i,j in zip(list,lengths): print(split(i,j)). Daftar listdan lengthsmemiliki panjang yang sama. j berganti-ganti: 5,4,5,4,5, dan fungsi split bekerja pada dua alternatif pertama, yaitu ia membagi daftar pertama idengan 5 dan 4, TETAPI pada iterasi berikutnya ia membaginya menjadi 4,4, 1. : \ Tolong balas jika Anda ingin saya menjelaskan lebih lanjut (poskan pertanyaan baru)
Mike Issa

15

Jika Anda tidak peduli dengan pesanan ...

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

list[::2]mendapatkan setiap elemen kedua dalam daftar mulai dari elemen 0.
list[1::2]dapatkan setiap elemen kedua dalam daftar mulai dari elemen 1.


4
Hati-hati menamai arg listdengan membayangi list(...)built-in. Saya sudah melihat lstdan list_digunakan secara umum untuk menghindarinya.
Taylor Edmiston

3
ini terasa paling pythonic (mengabaikan penamaan yang salah)
Tjorriemorrie


11

Berikut ini adalah solusi umum, pisahkan arr menjadi hitungan bagian

def split(arr, count):
     return [arr[i::count] for i in range(count)]

Ini kehilangan urutan daftar
Timmah

9
def splitter(A):
    B = A[0:len(A)//2]
    C = A[len(A)//2:]

 return (B,C)

Saya diuji, dan slash ganda diperlukan untuk memaksa int divisi di python 3. Posting asli saya benar, meskipun wysiwyg pecah di Opera, untuk beberapa alasan.


itu tidak menangani aneh len (A) - apakah Anda punya solusi untuk itu?
N997

6

Ada resi Python resmi untuk kasus yang lebih umum dari pemisahan array menjadi ukuran array yang lebih kecil 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)

Cuplikan kode ini berasal dari laman doc python itertools .


6

Menggunakan daftar slicing . Sintaks dasarnyamy_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]

Untuk mendapatkan bagian pertama dari daftar, Anda mengiris dari indeks pertama ke len(i)//2(di mana //adalah divisi integer - jadi 3//2 will give the floored result of1 , instead of the invalid list index of1.5`):

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

..dan tukar nilai di sekitar untuk mendapatkan paruh kedua:

>>> i[len(i)//2:]
[3, 4, 5]

bagaimana dengan daftar aneh len)
N997

@ N997 Kode masih harus bekerja; Anda hanya berakhir dengan jumlah item yang berbeda di setiap daftar. Jadi, katakanlah daftar itu terdiri dari tiga item, operator divisi 3//2memberikan hasil yang begitu banyak 1, kemudian Anda mendapatkan i[:1]yang memberi [0]dan dan i[1:]yang memberi[1, 2]
dbr

3

Jika Anda memiliki daftar besar, Lebih baik menggunakan itertools dan menulis fungsi untuk menghasilkan setiap bagian sesuai kebutuhan:

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

Anda bisa menggunakan ini seperti:

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

size = len(A) // 2

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

Outputnya adalah:

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

Terima kasih kepada @thefourtheye dan @Bede Constantinides


3

10 tahun kemudian .. Saya pikir - mengapa tidak menambahkan yang lain:

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

2

Sementara jawaban di atas kurang lebih benar, Anda dapat mengalami masalah jika ukuran array Anda tidak dapat dibagi 2, karena a / 2, menjadi aneh, adalah float di python 3.0, dan dalam versi sebelumnya jika Anda tentukan from __future__ import divisiondi awal skrip Anda. Anda dalam hal apa pun lebih baik pergi untuk divisi integer, yaitu a // 2, untuk mendapatkan "maju" kompatibilitas kode Anda.


2

Ini mirip dengan solusi lain, tetapi sedikit lebih cepat.

# 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:]

Penggunaan pintar pergeseran biner!
Janusz Skonieczny

0

Dengan petunjuk dari @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)

0
#for python 3
    A = [0,1,2,3,4,5]
    l = len(A)/2
    B = A[:int(l)]
    C = A[int(l):]       

0

Pandangan lain tentang masalah ini pada tahun 2020 ... Inilah generalisasi masalahnya. Saya menafsirkan 'membagi daftar menjadi setengah' menjadi .. (yaitu dua daftar saja dan tidak akan ada limpahan ke array ketiga dalam kasus yang aneh keluar dll). Misalnya, jika panjang array adalah 19 dan pembagian dengan dua menggunakan operator // memberikan 9, dan kita akan memiliki dua array dengan panjang 9 dan satu array (ketiga) dengan panjang 1 (jadi total tiga array). Jika kita menginginkan solusi umum untuk memberikan dua array sepanjang waktu, saya akan berasumsi bahwa kita senang dengan hasil array duo yang panjangnya tidak sama (satu akan lebih panjang dari yang lain). Dan itu dianggap ok untuk memiliki pesanan dicampur (berganti-ganti dalam kasus ini).

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

Konsep ini berfungsi untuk jumlah partisi daftar berapa pun yang Anda inginkan (Anda harus mengubah kode tergantung pada berapa banyak bagian daftar yang Anda inginkan). Dan agak mudah untuk ditafsirkan. Untuk mempercepat, Anda bahkan dapat menulis lingkaran ini dalam cython / C / C ++ untuk mempercepatnya. Kemudian lagi, saya sudah mencoba kode ini pada daftar yang relatif kecil ~ 10.000 baris dan selesai dalam sepersekian detik.

Hanya dua sen saya.

Terima kasih!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.