splitting a list into n groups
Peter Otten
__peter__ at web.de
Thu Oct 9 09:11:18 EDT 2003
Alex Martelli wrote:
> Rajarshi Guha wrote:
>
>> Hi,
>> is there an efficient (pythonic) way in which I could split a list into
>> say 5 groups? By split I mean the the first x members would be one group,
>> the next x members another group and so on 5 times. (Obviously x =
>> lengthof list/5)
>>
>> I have done this by a simple for loop and using indexes into the list.
>> But it does'nt seemm very elegant
>
> from itertools import islice
>
> def split_into_n_groups(alist, n=5):
> it = iter(alist)
> x = len(alist)/n # note: will just drop the last len(alist) % n
> items for i in range(n):
> yield list(islice(it, x))
>
> print list(split_into_n_groups(range(23)))
>
> emits:
>
> [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15], [16, 17,
> [[18,
> 19]]
>
> Of course, if you always want to return a list of lists (not a general
> sequence -- iterator -- with list items) you can simplify this, e.g.:
>
> def split_into_n_groups(alist, n=5):
> it = iter(alist)
> x = len(alist)/n # note: will just drop the last len(alist) % n
> items return [ list(islice(it, x)) for i in range(n) ]
>
> and just "print split_into_n_groups(range(23))".
Now I know why I couldn't come up with a solution. I didn' t look into the
itertools module :-)
Anyway, now you solved the main problem, here's how I would spread the
dropped items over the groups:
from itertools import islice
def split_into_n_groups(alist, n=5, noEmptyGroups=True):
it = iter(alist)
d, m = divmod(len(alist), n)
if d == 0 and noEmptyGroups:
n = m
for i in range(n):
yield list(islice(it, d+(i<m)))
N = 5
for k in range(23):
lol = list(split_into_n_groups(range(k), N))
cnt = reduce(lambda x, y: x + len(y), lol, 0)
assert cnt == k
assert len(lol) == min(k, N)
print lol
Peter
More information about the Python-list
mailing list