212

I am looking for a way to easily split a python list in half.

So that if I have an array:

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

I would be able to get:

B = [0,1,2]

C = [3,4,5]
corymathews
  • 12,289
  • 14
  • 57
  • 77

22 Answers22

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

If you want a function:

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)
maxymoo
  • 35,286
  • 11
  • 92
  • 119
Jason Coon
  • 17,601
  • 10
  • 42
  • 50
104

A little more generic solution (you can specify the number of parts you want, not just split 'in half'):

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)
Zoe
  • 27,060
  • 21
  • 118
  • 148
ChristopheD
  • 112,638
  • 29
  • 165
  • 179
  • 3
    When the list doesn't divide evenly (eg split_list([1,2,3], 2) ) this will actually return wanted_parts+1 lists. – Brian Apr 15 '09 at 18:27
  • That's correct, i was in doubt as what should be the right approach (have one more part or have the last list have one more item). I'll update my post, thanks for commenting. – ChristopheD Apr 15 '09 at 21:34
  • Actually, this still won't work: you may have a remainder > 1. split_list(range(5),3) will give 5 lists with the above code. Dealing with those cases is also trickier, as you need to spread the list out evenly (eg. for a 19 element list in 10 parts, you don't want 9*1 item and one with 9.) – Brian Apr 16 '09 at 12:51
  • 3
    A better way I think would be: length = len(alist); return [ alist[i*length // wanted_parts: (i+1)*length // wanted_parts] for i in range(wanted_parts) ]. That way you get an even as possible distribution, and always get exactly wanted_parts items (even pads with [] if wanted_parts > len(A)) – Brian Apr 16 '09 at 18:40
  • Very nice solution, thanks a lot. A lot shorter also then the way i was thinking in... i'll update my post. – ChristopheD Apr 16 '09 at 21:10
  • 2
    hi.. what does the symbol "//" means?? – frazman Jun 21 '12 at 06:01
  • 2
    @Fraz Its is meant as inline comment. Ignore "// wanted_parts" and "// wanted_parts" to make script execute. – PunjCoder Aug 02 '12 at 04:16
  • 27
    `//` means integer division. They should not be left out as they are quite essential in making this work. – Alphadelta14 Nov 20 '13 at 10:37
52
f = lambda A, n=3: [A[i:i+n] for i in range(0, len(A), n)]
f(A)

n - the predefined length of result arrays

Rod
  • 52,748
  • 3
  • 38
  • 55
Jaro
  • 813
  • 7
  • 10
  • 1
    This works great in my situation, however it is appending every other last index of each list into it's own list. Hard to explain. Please reply if you can help and I will explain more. – Mike Issa Feb 05 '16 at 18:59
41
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))

result:

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]
Lavande
  • 744
  • 8
  • 20
Siamand
  • 1,080
  • 10
  • 19
  • 1
    also useful to convert list to matrix – mpgn Nov 10 '15 at 21:05
  • This works, but not quite. I am using this function in a loop, and the lengths vary. In other words: `for i,j in zip(list,lengths): print(split(i,j))`. The `list` and `lengths` lists have the same length. j is alternating: 5,4,5,4,5, and the split function works on the first two alternations, ie it splits the first `i` of list by 5 and 4, BUT on the next iteration it splits it at 4,4,1. :\ Please reply if you would like me to explain more (post a new question) – Mike Issa Feb 05 '16 at 19:08
23

If you don't care about the order...

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

list[::2] gets every second element in the list starting from the 0th element.
list[1::2] gets every second element in the list starting from the 1st element.

AGS
  • 14,288
  • 5
  • 52
  • 67
sentythee
  • 331
  • 2
  • 2
16

Using list slicing. The syntax is basically my_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]

To get the first half of the list, you slice from the first index to len(i)//2 (where // is the integer division - so 3//2 will give the floored result of1, instead of the invalid list index of1.5`):

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

..and the swap the values around to get the second half:

>>> i[len(i)//2:]
[3, 4, 5]
dbr
  • 165,801
  • 69
  • 278
  • 343
  • 1
    what about odd len lists) – N997 May 01 '19 at 05:33
  • 1
    @N997 The code should still work; you just end up with different numbers of items in each list. So say the list is three items long, the division operator floors the result so `3//2` gives `1`, then you get `i[:1]` which gives you `[0]` and and `i[1:]` which gives `[1, 2]` – dbr May 16 '19 at 07:44
11

Here is a common solution, split arr into count part

def split(arr, count):
     return [arr[i::count] for i in range(count)]
Chris Song
  • 159
  • 1
  • 9
11
def splitter(A):
    B = A[0:len(A)//2]
    C = A[len(A)//2:]

 return (B,C)

I tested, and the double slash is required to force int division in python 3. My original post was correct, although wysiwyg broke in Opera, for some reason.

Stefan Kendall
  • 66,414
  • 68
  • 253
  • 406
11

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

John Montgomery
  • 8,868
  • 4
  • 33
  • 43
10

If you have a big list, It's better to use itertools and write a function to yield each part as needed:

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

You can use this like:

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

size = len(A) // 2

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

The output is:

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

Thanks to @thefourtheye and @Bede Constantinides

M.A. Heshmat Khah
  • 740
  • 12
  • 27
7

This is similar to other solutions, but a little faster.

# 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
  • 7,310
  • 3
  • 24
  • 41
6

There is an official Python receipe for the more generalized case of splitting an array into smaller arrays of size 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)

This code snippet is from the python itertools doc page.

Jonathan Berger
  • 1,043
  • 13
  • 17
4

10 years later.. I thought - why not add another:

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

While the answers above are more or less correct, you may run into trouble if the size of your array isn't divisible by 2, as the result of a / 2, a being odd, is a float in python 3.0, and in earlier version if you specify from __future__ import division at the beginning of your script. You are in any case better off going for integer division, i.e. a // 2, in order to get "forward" compatibility of your code.

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

General solution split list into n parts with parameter verification:

def sp(l,n):
    # split list l into n parts 
    if l: 
        p = len(l) if n < 1 else len(l) // n   # no split
        p = p if p > 0 else 1                  # split down to elements
        for i in range(0, len(l), p):
            yield l[i:i+p]
    else:
        yield [] # empty list split returns empty list
Jacek Błocki
  • 452
  • 3
  • 9
1

Since there was no restriction put on which package we can use.. Numpy has a function called split with which you can easily split an array any way you like.

Example

import numpy as np
A = np.array(list('abcdefg'))
np.split(A, 2)
zwep
  • 1,207
  • 12
  • 26
1

You can try something like this with numpy

import numpy as np
np.array_split([1,2,3,4,6,7,8], 2)

result:

[array([1, 2, 3, 4]), array([6, 7, 8])]
Vova
  • 3,117
  • 2
  • 15
  • 23
0

With hints from @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
  • 450
  • 1
  • 4
  • 12
0

Another take on this problem in 2020 ... Here's a generalization of the problem. I interpret the 'divide a list in half' to be .. (i.e. two lists only and there shall be no spillover to a third array in case of an odd one out etc). For instance, if the array length is 19 and a division by two using // operator gives 9, and we will end up having two arrays of length 9 and one array (third) of length 1 (so in total three arrays). If we'd want a general solution to give two arrays all the time, I will assume that we are happy with resulting duo arrays that are not equal in length (one will be longer than the other). And that its assumed to be ok to have the order mixed (alternating in this case).

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

This concept works for any amount of list partition as you'd like (you'd have to tweak the code depending on how many list parts you want). And is rather straightforward to interpret. To speed things up , you can even write this loop in cython / C / C++ to speed things up. Then again, I've tried this code on relatively small lists ~ 10,000 rows and it finishes in a fraction of second.

Just my two cents.

Thanks!

aaronlhe
  • 1,062
  • 10
  • 18
0
from itertools import islice 

Input = [2, 5, 3, 4, 8, 9, 1] 
small_list_length = [1, 2, 3, 1] 

Input1 = iter(Input) 

Result = [list(islice(Input1, elem)) for elem in small_list_length] 

print("Input list :", Input) 

print("Split length list: ", small_list_length) 

print("List after splitting", Result)
RiveN
  • 2,595
  • 11
  • 13
  • 26
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 22 '21 at 19:22
0

If you have Python 3.12 use batched:

from itertools import batched
array = [1,2,3,4,5,6,7,8,9,0]
chunks = batched(array, len(array)/2 + 1) 

This splits the array into chunks of specified size ( which is much more common operation that splitting into two pars).

user2555515
  • 779
  • 6
  • 20