1

I'm trying to split my string into chunks of 5 with this:

message = [no_space[i + i+5] for i in range(0, len(no_space))]

no_space is the same string without spaces

But the code keeps outputting:

IndexError: list index out of range

The string length is 171

So how do I fix this?

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Zac Cotterell
  • 105
  • 1
  • 1
  • 8
  • related: [What is the most “pythonic” way to iterate over a list in chunks?](http://stackoverflow.com/q/434287/4279) – jfs Mar 04 '16 at 22:16

3 Answers3

3

You likely meant to do this:

message = [no_space[i:i+5] for i in range(0, len(no_space), 5)]

Think about what would happen in your code for a specific i, say 90. 90 is perfectly within the range because the range you specified was from 0 up to (but not including) len(no_space), which is 171.

If i == 90, then i + i+5 == 90 + 90+5 == 185. You then request element 185 of no_space with no_space[185]. Since no_space is only 171 characters long, you can't request element 185, and so you get the IndexError.

Hopefully this example will explain how this new code works, with a short string and splitting into 3's:

>>> s = 'abcdefghijk'
>>> len(s)
11
>>> list(range(0, len(s), 3))
[0, 3, 6, 9]
>>> s[0:3]
'abc'
>>> s[3:6]
'def'
>>> s[6:9]
'ghi'
>>> s[9:12]
'jk'
>>> [(i, i+3) for i in range(0, len(s), 3)]
[(0, 3), (3, 6), (6, 9), (9, 12)]
>>> [s[i:i+3] for i in range(0, len(s), 3)]
['abc', 'def', 'ghi', 'jk']
Alyssa Haroldsen
  • 3,652
  • 1
  • 20
  • 35
  • Thansk your first block of code worked but what exactly does it mean? – Zac Cotterell Mar 16 '16 at 15:29
  • Thanks!! This code worked really well. However in don't quite get what it means so please could elaborate on this matter – Zac Cotterell Mar 18 '16 at 13:13
  • @ZacCotterell On mobile, but see list comprehension – Alyssa Haroldsen Mar 18 '16 at 14:41
  • Thanks but for some reason I'm still not getting it so could you maybe propose another way of doing the putting the message into groups of 5 – Zac Cotterell Mar 18 '16 at 15:21
  • Thanks but for some reason I'm still not getting it so could you maybe propose another way of doing the putting the message into groups of 5 – Zac Cotterell Mar 19 '16 at 15:47
  • @ZacCotterell This would be the most Pythonic way to do it that I know. Explain what you're not getting and show effort instead of repeating the same comment. Do you know how [list comprehensions](http://python-3-patterns-idioms-test.readthedocs.org/en/latest/Comprehensions.html) work? The interpreter code is intended to explain through code rather than words. Do you understand all of the interpreter code sample? – Alyssa Haroldsen Mar 19 '16 at 17:20
  • Yeah I did but for some odd reason I'm still not getting it?? Don't get me wrong i'm big into coding and get most things but this?? – Zac Cotterell Mar 23 '16 at 16:22
1

Funcy (a library offering various useful utilities, supporting both Python 2 and 3) offers a chunks function that does exactly this:

>>> import funcy
>>> data = b'abcdefghijklmnopqrstuvwxyz'
>>> list(funcy.chunks(6, data))
[b'abcdef', b'ghijkl', b'mnopqr', b'stuvwx', b'yz']   # Python 3
['abcdef', 'ghijkl', 'mnopqr', 'stuvwx', 'yz']        # Python 2.7

Alternatively, you could include a simple implementation of this in your program (compatible with both Python 2.7 and 3):

def chunked(size, source):
    for i in range(0, len(source), size):
        yield source[i:i+size]

It behaves the same (at least for your data; Funcy's chunks also works with iterators, this doesn't):

>>> list(chunked(6, data))
[b'abcdef', b'ghijkl', b'mnopqr', b'stuvwx', b'yz']   # Python 3
['abcdef', 'ghijkl', 'mnopqr', 'stuvwx', 'yz']        # Python 2.7
marcelm
  • 1,032
  • 11
  • 11
0
message = [no_space[i + i+5] for i in range(0, len(no_space))]

tries to get values for i within 5 of the final index. Thus when you try to use an i of 168 for example, you are going beyond the allowed index for i+5

I just noticed also the typo of using the + in the index of no_space. I think that you meant to get a slice. for example, when i is 10, you actually get the single element at index 25. when i is 83 you get an index of 171 which is an invalid index.

If you grab a slice of 5, you need to skip to the next available index (add 5 at a time) and fix the slice typo.

message = [no_space[i:i+5] for i in range(0, len(no_space), 5)]
sabbahillel
  • 4,357
  • 1
  • 19
  • 36