ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: Split a list into roughly equal-sized pieces
Submitter: Nick Matsakis (other recipes)
Last Updated: 2005/06/10
Version no: 1.0
Category:

 

Not Rated yet


Description:

Break a list into roughly equal sized pieces.

Source: Text Source

def split_seq(seq, size):
        newseq = []
        splitsize = 1.0/size*len(seq)
        for i in range(size):
                newseq.append(seq[int(round(i*splitsize)):int(round((i+1)*splitsize))])
        return newseq

Discussion:

Inspired by http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/425044

This requires that you know the length of the list beforehand, of course, so you can't use it with an arbitrary sequence as is. It's simple, but it's easy to create fencepost errors when implementing it.

>>> split_seq(range(10), 3)
[[0, 1, 2], [3, 4, 5, 6], [7, 8, 9]]



Add comment

Number of comments: 5

Naming suggestion, Jeremy Dunck, 2005/06/21
The second parameter, "size", would be better named "numPieces", since split_seq([]..., x) always returns a list with x pieces.
>>> split_seq(range(10), 1)
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]
>>> split_seq(range(10), 2)
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
Add comment

All integer approach, Paul Watson, 2005/06/22
Here is an all integer method that builds a list of ranges first, then splices the sequence.

def split_seq(seq, numpieces):
    seqlen = len(seq)
    d, m = divmod(seqlen, numpieces)
    rlist = range(0, ((d + 1) * (m + 1)), (d + 1))
    if d != 0: rlist += range(rlist[-1] + d, seqlen, d) + [seqlen]

    newseq = []
    for i in range(len(rlist) - 1):
        newseq.append(seq[rlist[i]:rlist[i + 1]])

    newseq += [[]] * max(0, (numpieces - seqlen))
    return newseq

Add comment

alternate implementation using integers, Greg Jorgensen, 2005/06/22
This version uses integer math and distributes the remaindered items evenly over the first few splits.

def split_seq(seq, p):
    newseq = []
    n = len(seq) / p    # min items per subsequence
    r = len(seq) % p    # remaindered items
    b,e = 0, n + min(1, r)  # first split
    for i in range(p):
        newseq.append(seq[b:e])
        r = max(0, r-1)  # use up remainders
        b,e = e, e + n + min(1, r)  # min(1,r) is always 0 or 1

    return newseq


>>> split_seq(range(10), 3)
[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> split_seq(range(11), 3)
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10]]
>>> split_seq(range(10), 4)
[[0, 1, 2], [3, 4, 5], [6, 7], [8, 9]]

Add comment

again, an integer approach, Marc Keller, 2005/06/23
def splitCeil(seq, m):
"""Distribute the seq elements in lists in m groups
according to quasi equitative distribution (decreasing order):
splitCeil(range(13), 4) --> seq = range(13), m=4
result : [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
"""
n,b,newseq=len(seq),0,[]
for k in range(m):
q,r=divmod(n-k,m)
a, b = b, b + q + (r!=0)
newseq.append(seq[a:b])
return newseq


def splitFloor(seq, m):
"""Distribute the seq elements in lists in m groups
according to quasi equitative distribution (increasing order):
seq = range(13), m=4
result : [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11, 12]]
"""
n,b,newseq=len(seq),0,[]
for k in range(m):
a, b = b, b + (n+k)//m
newseq.append(seq[a:b])
return newseq

Add comment

Sebastian Hempel, 2007/07/18
Another approach using slicing for the calculation of the list lengths.

def slice_it(li, cols=2): 
    start = 0 
    for i in xrange(cols): 
        stop = start + len(li[i::cols]) 
        yield li[start:stop] 
        start = stop

Add comment



Highest rated recipes:

1. A simple XML-RPC server

2. Web service accessible ...

3. Treat the Win32 Registry ...

4. Watching a directory ...

5. Union Find data structure

6. Function Decorators by ...

7. MS SQL Server log monitor

8. Table objects with ...

9. wx twisted support using ...

10. More accurate sum




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.