82

Is there a way to take a string that is 4*x characters long, and cut it into 4 strings, each x characters long, without knowing the length of the string?

For example:

>>>x = "qwertyui"
>>>split(x, one, two, three, four)
>>>two
'er'
Alexander
  • 23,432
  • 11
  • 63
  • 73
tkbx
  • 15,602
  • 32
  • 87
  • 122

16 Answers16

119
>>> x = "qwertyui"
>>> chunks, chunk_size = len(x), len(x)//4
>>> [ x[i:i+chunk_size] for i in range(0, chunks, chunk_size) ]
['qw', 'er', 'ty', 'ui']
Alexander
  • 23,432
  • 11
  • 63
  • 73
27
  • :param s: str; source string
  • :param w: int; width to split on

Using the textwrap module:

PyDocs-textwrap

import textwrap
def wrap(s, w):
    return textwrap.fill(s, w)

:return str:

Inspired by Alexander's Answer

PyDocs-data structures

def wrap(s, w):
    return [s[i:i + w] for i in range(0, len(s), w)]
  • :return list:

Inspired by Eric's answer

PyDocs-regex

import re
def wrap(s, w):    
    sre = re.compile(rf'(.{{{w}}})')
    return [x for x in re.split(sre, s) if x]
  • :return list:
gil.fernandes
  • 12,978
  • 5
  • 63
  • 76
JerodG
  • 1,248
  • 1
  • 16
  • 34
26

I tried Alexanders answer but got this error in Python3:

TypeError: 'float' object cannot be interpreted as an integer

This is because the division operator in Python3 is returning a float. This works for me:

>>> x = "qwertyui"
>>> chunks, chunk_size = len(x), len(x)//4
>>> [ x[i:i+chunk_size] for i in range(0, chunks, chunk_size) ]
['qw', 'er', 'ty', 'ui']

Notice the // at the end of line 2, to ensure truncation to an integer.

Machavity
  • 30,841
  • 27
  • 92
  • 100
fnkr
  • 9,428
  • 6
  • 54
  • 61
  • 4
    You are probably using Python3, where the division operator returns a float. You can use the truncating division operator `//` instead of casting to integer: `len(x)//4`. Also, I think the cast in `int(len(x))` is unnecessary. – BoppreH Sep 04 '14 at 19:05
  • i came up with this answer for dividing my text into two pieces but the code divide it into 3 if you change len(x)//4 to len(x)//2. So i add +1 to the end of len(x)//2. For any of you that decide to use this answer. – Kemal Can Kara Sep 19 '18 at 11:35
13
some_string="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
x=3 
res=[some_string[y-x:y] for y in range(x, len(some_string)+x,x)]
print(res)

will produce

['ABC', 'DEF', 'GHI', 'JKL', 'MNO', 'PQR', 'STU', 'VWX', 'YZ']
12

In Split string every nth character?, "the wolf" gives the most concise answer:

>>> import re
>>> re.findall('..','1234567890')
['12', '34', '56', '78', '90']
Ethan Bradford
  • 710
  • 8
  • 10
7

Here is a one-liner that doesn't need to know the length of the string beforehand:

from functools import partial
from StringIO import StringIO

[l for l in iter(partial(StringIO(data).read, 4), '')]

If you have a file or socket, then you don't need the StringIO wrapper:

[l for l in iter(partial(file_like_object.read, 4), '')]
bobchase
  • 219
  • 3
  • 3
7
def split2len(s, n):
    def _f(s, n):
        while s:
            yield s[:n]
            s = s[n:]
    return list(_f(s, n))
4

Got an re trick:

In [28]: import re

In [29]: x = "qwertyui"

In [30]: [x for x in re.split(r'(\w{2})', x) if x]
Out[30]: ['qw', 'er', 'ty', 'ui']

Then be a func, it might looks like:

def split(string, split_len):
    # Regex: `r'.{1}'` for example works for all characters
    regex = r'(.{%s})' % split_len
    return [x for x in re.split(regex, string) if x]
Eric
  • 295
  • 3
  • 6
  • This is interesting. How exactly does this regex with split work and why does it produce a leading and lagging empty match? – Bill Aug 19 '20 at 20:08
  • B.t.w. you could also do this: `list(filter(None, re.split(r'(\w{2})', x)))` – Bill Aug 19 '20 at 20:09
  • 1
    This also seems to work and is simpler: `re.findall(r'(\w{2})', x) ` – Bill Aug 19 '20 at 20:11
1

Here are two generic approaches. Probably worth adding to your own lib of reusables. First one requires the item to be sliceable and second one works with any iterables (but requires their constructor to accept iterable).

def split_bylen(item, maxlen):
    '''
    Requires item to be sliceable (with __getitem__ defined)
    '''
    return [item[ind:ind+maxlen] for ind in range(0, len(item), maxlen)]
    #You could also replace outer [ ] brackets with ( ) to use as generator.

def split_bylen_any(item, maxlen, constructor=None):
    '''
    Works with any iterables.
    Requires item's constructor to accept iterable or alternatively 
    constructor argument could be provided (otherwise use item's class)
    '''
    if constructor is None: constructor = item.__class__
    return [constructor(part) for part in zip(* ([iter(item)] * maxlen))]
    #OR: return map(constructor, zip(* ([iter(item)] * maxlen)))
    #    which would be faster if you need an iterable, not list

So, in topicstarter's case, the usage is:

string = 'Baboons love bananas'
parts = 5
splitlen = -(-len(string) // parts) # is alternative to math.ceil(len/parts)

first_method = split_bylen(string, splitlen)
#Result :['Babo', 'ons ', 'love', ' ban', 'anas']

second_method = split_bylen_any(string, splitlen, constructor=''.join)
#Result :['Babo', 'ons ', 'love', ' ban', 'anas']
thodnev
  • 1,564
  • 16
  • 20
1
length = 4
string = "abcdefgh"
str_dict = [ o for o in string ]
parts = [ ''.join( str_dict[ (j * length) : ( ( j + 1 ) * length ) ]   ) for j in xrange(len(string)/length  )]
Frederico Wu
  • 61
  • 1
  • 1
  • Hi Frederico, welcome to SO! It might be worthwhile explaining why you did what you did in this answer so that newcomers to the language and ideas you have shown can understand why this is a good course of action to take. – Ethan Field Oct 09 '17 at 15:02
1
# spliting a string by the length of the string

def len_split(string,sub_string):
    n,sub,str1=list(string),len(sub_string),')/^0*/-'
    for i in range(sub,len(n)+((len(n)-1)//sub),sub+1):
        n.insert(i,str1)   
    n="".join(n)
    n=n.split(str1)
    return n

x="divyansh_looking_for_intership_actively_contact_Me_here"
sub="four"
print(len_split(x,sub))

# Result-> ['divy', 'ansh', 'tiwa', 'ri_l', 'ooki', 'ng_f', 'or_i', 'nter', 'ship', '_con', 'tact', '_Me_', 'here']
Divyansh
  • 71
  • 2
  • 6
1

There is a built in function in python for that

import textwrap

text = "Your Text.... and so on"
width = 5 #

textwrap.wrap(text,width)

Vualla

sivi
  • 10,654
  • 2
  • 52
  • 51
0

And for dudes who prefer it to be a bit more readable:

def itersplit_into_x_chunks(string,x=10): # we assume here that x is an int and > 0
    size = len(string)
    chunksize = size//x
    for pos in range(0, size, chunksize):
        yield string[pos:pos+chunksize]

output:

>>> list(itersplit_into_x_chunks('qwertyui',x=4))
['qw', 'er', 'ty', 'ui']
Nils Lindemann
  • 1,146
  • 1
  • 16
  • 26
0

My solution

   st =' abs de fdgh  1234 556 shg shshh'
   print st

   def splitStringMax( si, limit):
    ls = si.split()
    lo=[]
    st=''
    ln=len(ls)
    if ln==1:
        return [si]
    i=0
    for l in ls:
        st+=l
        i+=1
        if i <ln:
            lk=len(ls[i])
            if (len(st))+1+lk < limit:
                st+=' '
                continue
        lo.append(st);st=''
    return lo

   ############################

   print  splitStringMax(st,7)
   # ['abs de', 'fdgh', '1234', '556', 'shg', 'shshh']
    print  splitStringMax(st,12)

   # ['abs de fdgh', '1234 556', 'shg shshh']
Messa
  • 24,321
  • 6
  • 68
  • 92
  • 1
    I don't know why people are degrading answered, users have different scenario this is the scenario which I need so up vote from my side. – Ganesh Oct 02 '20 at 12:15
0

The string splitting is required in many cases like where you have to sort the characters of the string given, replacing a character with an another character etc. But all these operations can be performed with the following mentioned string splitting methods.

The string splitting can be done in two ways:

  1. Slicing the given string based on the length of split.

  2. Converting the given string to a list with list(str) function, where characters of the string breakdown to form the the elements of a list. Then do the required operation and join them with 'specified character between the characters of the original string'.join(list) to get a new processed string.

pmsh.93
  • 1
  • 1
  • 2
0
l = 'abcdefghijklmn'

def group(l,n):
    tmp = len(l)%n
    zipped = zip(*[iter(l)]*n)
    return zipped if tmp == 0 else zipped+[tuple(l[-tmp:])]

print group(l,3)
Zhang Tong
  • 4,569
  • 3
  • 19
  • 38
  • 2
    While this code snippet may solve the question, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations! – kayess Dec 01 '16 at 08:40