Reputation: 13447
I want to write a function that takes items from a list and groups them into groups of size n.
Ie, for n = 5, [1, 2, 3, 4, 5, 6, 7] would become [[1, 2, 3, 4, 5], [6, 7]].
What's the best python idiomatic way to do this?
Upvotes: 2
Views: 312
Reputation: 8721
Solutions using ranges with steps only work on sequences such as lists and tuples (not iterators). They also aren't as efficient as they can be, since they access the sequence many times instead of iterating over it once.
Here's a version which supports iterators and only iterates over the input once, creating a list of lists:
def blockify(iterator, blocksize):
"""Split the items in the given iterator into blocksize-sized lists.
If the number of items in the iterator doesn't divide by blocksize,
a smaller block containing the remaining items is added to the result.
"""
blocks = []
for index, item in enumerate(iterator):
if index % blocksize == 0:
block = []
blocks.append(block)
block.append(item)
return blocks
And now an iterator version which returns an iterator of tuples, doesn't have a memory overhead, and allows choosing whether to include the remainder. Note that the output can be converted into a list via list(blockify(...)).
from itertools import islice
def blockify(iterator, blocksize, include_remainder=True):
"""Split the items in the given iterator into blocksize-sized tuples.
If the number of items in the iterator doesn't divide by blocksize and
include_remainder is True, a smaller block containing the remaining items
is added to the result; if include_remainder is False the remaining items
are discarded.
"""
iterator = iter(iterator) # we need an actual iterator
while True:
block = tuple(islice(iterator, blocksize))
if len(block) < blocksize:
if len(block) > 0 and include_remainder:
yield block
break
yield block
Upvotes: 1
Reputation: 1912
I don't know of a good command to do this, but here's a way to do it with a list comprehension:
l = [1,2,3,4,5,6,7]
n = 5
newlist = [l[i:i+n] for i in range(0,len(l),n)]
Edit: as a commenter pointed out, I had accidentally put l[i:i+n] in a list.
Upvotes: 1
Reputation: 993901
You could do this:
[a[x:x+n] for x in range(0, len(a), n)]
(In Python 2, use xrange
for efficiency; in Python 3 use range
as above.)
Upvotes: 2