31

I can't figure out how to do this with string methods:

In my file I have something like 1.012345e0070.123414e-004-0.1234567891.21423... which means there is no delimiter between the numbers.

Now if I read a line from this file I get a string like above which I want to split after e.g. 12 characters. There is no way to do this with something like str.split() or any other string method as far as I've seen but maybe I'm overlooking something?

Thx

unholysampler
  • 17,141
  • 7
  • 47
  • 64
BandGap
  • 311
  • 1
  • 3
  • 3

8 Answers8

35

Since you want to iterate in an unusual way, a generator is a good way to abstract that:

def chunks(s, n):
    """Produce `n`-character chunks from `s`."""
    for start in range(0, len(s), n):
        yield s[start:start+n]

nums = "1.012345e0070.123414e-004-0.1234567891.21423"
for chunk in chunks(nums, 12):
    print chunk

produces:

1.012345e007
0.123414e-00
4-0.12345678
91.21423

(which doesn't look right, but those are the 12-char chunks)

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
19

You're looking for string slicing.

>>> x = "1.012345e0070.123414e-004-0.1234567891.21423"
>>> x[2:10]
'012345e0'
J.J.
  • 5,019
  • 2
  • 28
  • 26
8
line = "1.012345e0070.123414e-004-0.1234567891.21423"
firstNumber = line[:12]
restOfLine = line[12:]

print firstNumber
print restOfLine

Output:

1.012345e007
0.123414e-004-0.1234567891.21423
mopsled
  • 8,445
  • 1
  • 38
  • 40
6

you can do it like this:

step = 12
for i in range(0, len(string), 12):
    slice = string[i:step]
    step += 12

in this way on each iteration you will get one slice of 14 characters.

Aamir Rind
  • 38,793
  • 23
  • 126
  • 164
3

I stumbled on this while looking for a solution for a similar problem - but in my case I wanted to split string into chunks of differing lengths. Eventually I solved it with RE

In [13]: import re

In [14]: random_val = '07eb8010e539e2621cb100e4f33a2ff9'

In [15]: dashmap=(8, 4, 4, 4, 12)

In [16]: re.findall(''.join('(\S{{{}}})'.format(l) for l in dashmap), random_val)
Out[16]: [('07eb8010', 'e539', 'e262', '1cb1', '00e4f33a2ff9')]

Bonus

For those who may find it interesting - I tried to create pseudo-random ID by specific rules, so this code is actually part of the following function

import re, time, random 
def random_id_from_time_hash(dashmap=(8, 4, 4, 4, 12)):
     random_val = ''
     while len(random_val) < sum(dashmap):
         random_val += '{:016x}'.format(hash(time.time() * random.randint(1, 1000)))
     return '-'.join(re.findall(''.join('(\S{{{}}})'.format(l) for l in dashmap), random_val)[0])
volcano
  • 3,578
  • 21
  • 28
3

I always thought, since string addition operation is possible by a simple logic, may be division should be like this. When divided by a number, it should split by that length. So may be this is what you are looking for.

class MyString:
    def __init__(self, string):
        self.string = string
    def __div__(self, div):
        l = []
        for i in range(0, len(self.string), div):
            l.append(self.string[i:i+div])
        return l

>>> m = MyString(s)
>>> m/3
['abc', 'bdb', 'fbf', 'bfb']


>>> m = MyString('abcd')
>>> m/3
['abc', 'd']

If you don't want to create an entirely new class, simply use this function that re-wraps the core of the above code,

>>> def string_divide(string, div):
       l = []
       for i in range(0, len(string), div):
           l.append(string[i:i+div])
       return l

>>> string_divide('abcdefghijklmnopqrstuvwxyz', 15)
['abcdefghijklmno', 'pqrstuvwxyz']
Joses Ho
  • 118
  • 10
Arindam Roychowdhury
  • 5,927
  • 5
  • 55
  • 63
3
from itertools import izip_longest

def grouper(n, iterable, padvalue=None):
    return izip_longest(*[iter(iterable)]*n, fillvalue=padvalue)
BrainStorm
  • 2,036
  • 1
  • 16
  • 23
2

Try this function:

x = "1.012345e0070.123414e-004-0.1234567891.21423"
while len(x)>0:
  v = x[:12]
  print v
  x = x[12:]
Somnath Muluk
  • 55,015
  • 38
  • 216
  • 226
Andrey Agibalov
  • 7,624
  • 8
  • 66
  • 111