Etgar
Etgar

Reputation: 5924

How to split a string into a fixed number of parts in Python?

I know the method textwrap.wrap, but this method splits a string to a fixed length for each part, but I'm looking for a function in python that splits the string the string into fixed num of parts.

For example:string = "Hello, my name is foo"
and foo(string, 7)
returns ['Hel', 'lo,', ' my', ' na', 'me ', 'is ', 'foo']

Algorithmically, I know how to implement this method, but I want to know if there a module that provides it or a "magic function" in the regex module that answers this problem...

Upvotes: 1

Views: 1852

Answers (4)

pmi
pmi

Reputation: 351

Yet another solution to this problem...

# split text to parts                                                           
def split_to_parts(txt,parts):
  # return array
  ret=[]
  # calculate part length
  part_len=int(len(txt)/parts)
  # iterate and fill the return array
  for i in range(parts):
    # divide the text
    piece=txt[part_len*i:part_len*(i+1)]
    # add it to the return array
    ret.append(piece)
  # return the array
  return(ret)

txt = "Hello, my name is foo"
parts=7    
split_to_parts(txt,parts)

# output:
# ['Hel', 'lo,', ' my', ' na', 'me ', 'is ', 'foo']

Upvotes: 0

gil
gil

Reputation: 2134

I don't know if any module does this... but I feel compelled to say that the problem here is basically What is the most "pythonic" way to iterate over a list in chunks?, except you have strings instead of lists. But the most pythonic way there should also be the most pythonic here, I suppose, and it's a good thing if you can avoid re. So here is the solution (not sure what you want if the string cannot be evenly divided by the number of parts; assuming you simply discard the "remainder"):

# python 3 version
def foo(string, n):
    part_len = -(-len(string) // n)  # same as math.ceil(len(string) / n)
    return [''.join(x) for x in zip(*[iter_str] * part_len)]

Thus:

>>> s = "Hello, my name is foo"
>>> foo(s, 7)
['Hel', 'lo,', ' my', ' na', 'me ', 'is ', 'foo']
>>> foo(s, 6)
['Hell', 'o, m', 'y na', 'me i', 's fo']

Now admittedly having foo(s, 6) return a list of length 5 is somewhat surprising. Maybe you want to raise an exception instead. If you want to keep the remainder, then use zip_longest

from itertools import zip_longest

def foo2(string, n, pad=''):
    part_len = -(-len(string) // n)
    return [''.join(x) for x in zip_longest(*[iter(string)] * part_len, fillvalue=pad)]

>>> foo2(s, 6)
['Hell', 'o, m', 'y na', 'me i', 's fo', 'o']
>>> foo2(s, 6, pad='?')
['Hell', 'o, m', 'y na', 'me i', 's fo', 'o???']

Upvotes: 1

vks
vks

Reputation: 67968

One approach can be using re.

import re
string = "Hello, my name is foo"
def foo(string, parts):
    x=len(string)/parts
    print re.findall(r".{"+str(x)+r"}|.+?$",string)

foo(string,7)

Output:['Hel', 'lo,', ' my', ' na', 'me ', 'is ', 'foo']

Upvotes: 1

pnovotnak
pnovotnak

Reputation: 4581

I don't think there is a builtin, but I think you could do it with regex: https://stackoverflow.com/a/9477447/1342445

In that case your function generates the regex from the len(input) / int(parts) of the string, and raises an error if it's not divisible by the input. Would be much simpler with undefined remainder behavior :)

I think it would look something like:

import re


def split_into(string: str, parts: int):
    if (len(string) % parts) != 0:
        raise NotImplementedError('string is not divisible by # parts')

    chunk_size = len(string) / parts
    regex = '.'*chunk_size
    return re.findall(regex, string)

Upvotes: 0

Related Questions