I would like to break up a list into sublists of 3 elements each. I have this code, but it will give an index error when the length of the list is not divisible by 3.

mylist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

# groups of n
n = 3
newlist = []
for ix in range(n, len(mylist) + n, n):
    sublist = [mylist[ix-3], mylist[ix-2], mylist[ix-1]]
    #print(ix, sublist)
    newlist.append(sublist)

print(newlist)

''' output -->
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
'''

Is there a better way to do this?
I seem to have a mental block!

Recommended Answers

All 9 Replies

How about after each element added to the list check its size, if the size says it has 3 elements print it and set the list back to empty. Once all elements from the original big string/array are passed through, stop execution

It was my first code snippet in daniweb :). Here we go

>>> splitIt =  lambda d, s: [s[i:i+d] for i in range(0, len(s), d)]
>>> mylist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> splitIt(3, mylist)
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]

See also the grouper() iterable in the recipes at the end of itertools documentation.

There are several ways to do this. I prefer a while loop

##  Not divisible by 3
mylist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

newlist = []
sublist=[]
ctr = 0

while ctr < len(mylist):
    sublist.append(mylist[ctr])
    ctr += 1
    if not ctr % 3:
        newlist.append(sublist)
        sublist = []

if len(sublist):
    newlist.append(sublist)

print(newlist)
[mylist[i:i+3] for i in range(0,len(mylist),3)]
>>> zip(*[iter(mylist)]*3)
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)]

Nice, but it shortens the list if the length is not a multiple of 3.

Nice, but it shortens the list if the length is not a multiple of 3.

Yes that's right,an other solution is to use map().

>>> mylist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> mylist_1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> map(None, *[iter(mylist)]*3)
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)]
>>> map(None, *[iter(mylist_1)]*3)
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, None)]

So here is None used as fill value.
If this this is not desirable,then other soultion in this post are fine.

Wow, lots of options! I myself am more partial to slicing, unless you have to pad your resulting sequence.

Thank y'all!
I guess I will go with the slicing example, since I don't need to pad.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.