1

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...

Vincent Savard
  • 34,979
  • 10
  • 68
  • 73
Etgar
  • 5,774
  • 2
  • 16
  • 30
  • @Stidgeon I mentioned that I don't want the textwrap.wrap method :) – Etgar Feb 19 '16 at 19:19
  • 1
    How do you want it to be handled when the string cannot be divided evenly? For example if the string length is 9 and you want 4 parts do you want the parts to have lengths [3, 2, 2, 2]? Do you want an error. Do you want the bigger piece at the beginning or end? – Steven Rumbalski Feb 19 '16 at 19:25
  • 1
    Voted to reopen because the linked question asked for evenly sized chunks where this question asks for a particular number of chunks. – Steven Rumbalski Feb 19 '16 at 19:34
  • You could `textwrap.wrap(your_string, len(your_string)/number_of_chunks)`, depending on how you want to manage cases when the string cannot be divided in `number_of_chunks` parts. – Vincent Savard Feb 19 '16 at 19:38

4 Answers4

1

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']

vks
  • 67,027
  • 10
  • 91
  • 124
  • `foo(string,6)` returns the same result as `foo(string,7)`. `foo(string,5)` leaves off the last letter of the sentence. (Temporary downvote until fixed. Sorry.) – Steven Rumbalski Feb 19 '16 at 19:21
  • @StevenRumbalski fixed.............foo(6) and foo(7) will be same .you can have `3.5` letters – vks Feb 19 '16 at 19:27
  • Giving one extra item when the string is not evenly divisible is a surprising result. You may want to call it out in your answer. – Steven Rumbalski Feb 19 '16 at 19:29
1

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???']
Community
  • 1
  • 1
gil
  • 2,086
  • 12
  • 13
0

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)
Community
  • 1
  • 1
pnovotnak
  • 4,341
  • 2
  • 27
  • 38
0

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']
pmi
  • 341
  • 3
  • 6