0

Considering the text line with numbers, I want to slice it into pieces with ten characters but I want to accept the fragments with less then ten if they exist.

With my script, I can obtain four complete groups, using 10 as fixed length, but the last four characters are missed.

The correct output would be:

['0123456789', '0123456789', '0123456789', '0123456789', '0123']

But I just obtain this:

['0123456789', '0123456789', '0123456789', '0123456789']

Any suggestion to fix these line in order to get the expected result?

step = 10
seq = "0123456789012345678901234567890123"
parts = []
for i in range(len(seq)/step): 
    sub = seq[i * step: (i + 1) * step]
    parts.append(sub)
print parts
F.Lira
  • 663
  • 2
  • 6
  • 19
  • I think at least some of the answers to [How do you split a list into evenly sized chunks?](https://stackoverflow.com/q/312443/953482) allow for partial final chunks - try out a couple of those. – Kevin Apr 24 '18 at 15:54

4 Answers4

4

You can modify the range to advance by step:

step = 10
seq = "0123456789012345678901234567890123"
parts = []
for i in range(0, len(seq), step):
    sub = seq[i: i + step]
    parts.append(sub)
print parts

Output:

['0123456789', '0123456789', '0123456789', '0123']
jdehesa
  • 58,456
  • 7
  • 77
  • 121
2

range(len(seq)/step) will return [0, 1, 2], so you will only do 3 iterations of your loop.

You can modify it to add 1 as follows:

for i in range(len(seq)//step+1): 

But if sequence is an exact multiple of step, this will result in the last element of your list being an empty string ''. To fix that, you can either add an if statement to not append an empty string or compute the range differently. I recommend the following:

step = 10
seq = "0123456789012345678901234567890123"
parts = []
nSteps = len(seq)//step + (0 if len(seq)%step == 0 else 1)
for i in range(nSteps): 
    sub = seq[i * step: (i + 1) * step]
    parts.append(sub)
print(parts)
#['0123456789', '0123456789', '0123456789', '0123']

Another thing to note is that I am using // instead of / to denote integer division. This doesn't make a difference in python2, but the latter would break your code in python3. Similarly, I am using print as a function rather than a statement.

pault
  • 41,343
  • 15
  • 107
  • 149
  • Note that, if len(seq) is a multiple of step, it will do an extra iteration. E.g. using `seq = "012345678901234567890123456789"` and `step=10` it returns `['0123456789', '0123456789', '0123456789', '']` – francisco sollima Apr 24 '18 at 15:57
  • @franciscosollima yes I realized this and posted an update. Thanks for pointing it out. – pault Apr 24 '18 at 16:05
1
step = 10
seq = "0123456789012345678901234567890123"
chunks = []
while len(seq) > 0:
   chunks.append(seq[:step])
   seq = seq[step:]

In each iteration, this is eating up the step-length beginning part of seq and appends it to the chunks list. Since seq[:step] also works if len(seq) < step, this also works fine in the last iteration, regardless of the length of the last portion.

Jonathan Scholbach
  • 4,925
  • 3
  • 23
  • 44
0

You might want to try a condition that allows for the last case to show up:

step = 10
seq = "0123456789012345678901234567890123"
parts = []
for i in range(len(seq)/step): 
    if i> (len(seq)/step)*(step - 1):
        sub = seq[(i-1)*step:]
    else:
        sub = seq[i * step: (i + 1) * step]
    parts.append(sub)
print parts
ohduran
  • 787
  • 9
  • 15