Is it possible to split a string every nth character?
For example, suppose I have a string containing the following:
'1234567890'
How can I get it to look like this:
['12','34','56','78','90']
Georgy
10.8k7 gold badges62 silver badges68 bronze badges
asked Feb 28, 2012 at 1:48
1
>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range[0, len[line], n]]
['12', '34', '56', '78', '90']
answered Feb 28, 2012 at 2:02
4
Just to be complete, you can do this with a regex:
>>> import re
>>> re.findall['..','1234567890']
['12', '34', '56', '78', '90']
For odd number of chars you can do this:
>>> import re
>>> re.findall['..?', '123456789']
['12', '34', '56', '78', '9']
You can also do the following, to simplify the regex for longer chunks:
>>> import re
>>> re.findall['.{1,2}', '123456789']
['12', '34', '56', '78', '9']
And you can use re.finditer
if the string is long to generate chunk by chunk.
Georgy
10.8k7 gold badges62 silver badges68 bronze badges
answered Feb 28, 2012 at 6:31
the wolfthe wolf
32.8k12 gold badges53 silver badges71 bronze badges
5
There is already an inbuilt function in python for this.
>>> from textwrap import wrap
>>> s = '1234567890'
>>> wrap[s, 2]
['12', '34', '56', '78', '90']
This is what the docstring for wrap says:
>>> help[wrap]
'''
Help on function wrap in module textwrap:
wrap[text, width=70, **kwargs]
Wrap a single paragraph of text, returning a list of wrapped lines.
Reformat the single paragraph in 'text' so it fits in lines of no
more than 'width' columns, and return a list of wrapped lines. By
default, tabs in 'text' are expanded with string.expandtabs[], and
all other whitespace characters [including newline] are converted to
space. See TextWrapper class for available keyword args to customize
wrapping behaviour.
'''
answered Feb 19, 2018 at 6:57
10
Another common way of grouping elements into n-length groups:
>>> s = '1234567890'
>>> map[''.join, zip[*[iter[s]]*2]]
['12', '34', '56', '78', '90']
This method comes straight from the docs for zip[]
.
answered Feb 28, 2012 at 2:25
Andrew ClarkAndrew Clark
195k33 gold badges263 silver badges296 bronze badges
5
I think this is shorter and more readable than the itertools version:
def split_by_n[seq, n]:
'''A generator to divide a sequence into chunks of n units.'''
while seq:
yield seq[:n]
seq = seq[n:]
print[list[split_by_n['1234567890', 2]]]
answered Feb 28, 2012 at 1:53
Russell BorogoveRussell Borogove
17.8k3 gold badges39 silver badges48 bronze badges
2
Using more-itertools from PyPI:
>>> from more_itertools import sliced
>>> list[sliced['1234567890', 2]]
['12', '34', '56', '78', '90']
answered Jun 22, 2017 at 10:19
Tim DielsTim Diels
3,0182 gold badges18 silver badges22 bronze badges
I like this solution:
s = '1234567890'
o = []
while s:
o.append[s[:2]]
s = s[2:]
answered Sep 12, 2015 at 23:14
vlkvlk
2,3813 gold badges31 silver badges33 bronze badges
You could use the grouper[]
recipe from itertools
:
Python 2.x:
from itertools import izip_longest
def grouper[iterable, n, fillvalue=None]:
"Collect data into fixed-length chunks or blocks"
# grouper['ABCDEFG', 3, 'x'] --> ABC DEF Gxx
args = [iter[iterable]] * n
return izip_longest[fillvalue=fillvalue, *args]
Python 3.x:
from itertools import zip_longest
def grouper[iterable, n, fillvalue=None]:
"Collect data into fixed-length chunks or blocks"
# grouper['ABCDEFG', 3, 'x'] --> ABC DEF Gxx"
args = [iter[iterable]] * n
return zip_longest[*args, fillvalue=fillvalue]
These functions are memory-efficient and work with any iterables.
answered Oct 3, 2015 at 20:16
Eugene YarmashEugene Yarmash
134k37 gold badges309 silver badges364 bronze badges
1
This can be achieved by a simple for loop.
a = '1234567890a'
result = []
for i in range[0, len[a], 2]:
result.append[a[i : i + 2]]
print[result]
The output looks like ['12', '34', '56', '78', '90', 'a']
answered May 22, 2020 at 18:02
Kasem777Kasem777
5595 silver badges10 bronze badges
3
I was stucked in the same scenrio.
This worked for me
x="1234567890"
n=2
list=[]
for i in range[0,len[x],n]:
list.append[x[i:i+n]]
print[list]
Output
['12', '34', '56', '78', '90']
answered Nov 28, 2019 at 14:54
StrickStrick
1,3747 silver badges15 bronze badges
1
Try the following code:
from itertools import islice
def split_every[n, iterable]:
i = iter[iterable]
piece = list[islice[i, n]]
while piece:
yield piece
piece = list[islice[i, n]]
s = '1234567890'
print list[split_every[2, list[s]]]
answered Feb 28, 2012 at 1:52
enderskillenderskill
6,9483 gold badges23 silver badges23 bronze badges
1
Try this:
s='1234567890'
print[[s[idx:idx+2] for idx,val in enumerate[s] if idx%2 == 0]]
Output:
['12', '34', '56', '78', '90']
answered Jul 10, 2018 at 3:46
U12-ForwardU12-Forward
66.1k13 gold badges76 silver badges96 bronze badges
0
>>> from functools import reduce
>>> from operator import add
>>> from itertools import izip
>>> x = iter['1234567890']
>>> [reduce[add, tup] for tup in izip[x, x]]
['12', '34', '56', '78', '90']
>>> x = iter['1234567890']
>>> [reduce[add, tup] for tup in izip[x, x, x]]
['123', '456', '789']
answered Feb 28, 2012 at 1:56
ben wben w
2,45212 silver badges17 bronze badges
0
As always, for those who love one liners
n = 2
line = "this is a line split into n characters"
line = [line[i * n:i * n+n] for i,blah in enumerate[line[::n]]]
answered May 20, 2016 at 20:00
SqripterSqripter
992 silver badges7 bronze badges
4
more_itertools.sliced
has been mentioned before. Here are four more options from the more_itertools
library:
s = "1234567890"
["".join[c] for c in mit.grouper[2, s]]
["".join[c] for c in mit.chunked[s, 2]]
["".join[c] for c in mit.windowed[s, 2, step=2]]
["".join[c] for c in mit.split_after[s, lambda x: int[x] % 2 == 0]]
Each of the latter options produce the following output:
['12', '34', '56', '78', '90']
Documentation for discussed options: grouper
, chunked
,
windowed
, split_after
answered Feb 9, 2018 at 1:16
pylangpylang
36.2k11 gold badges120 silver badges110 bronze badges
0
A simple recursive solution for short string:
def split[s, n]:
if len[s] < n:
return []
else:
return [s[:n]] + split[s[n:], n]
print[split['1234567890', 2]]
Or in such a form:
def split[s, n]:
if len[s] < n:
return []
elif len[s] == n:
return [s]
else:
return split[s[:n], n] + split[s[n:], n]
, which illustrates the typical divide and conquer pattern in recursive approach more explicitly [though practically it is not necessary to do it this way]
answered Oct 22, 2018 at 10:25
englealuzeenglealuze
1,40511 silver badges17 bronze badges
A solution with groupby
:
from itertools import groupby, chain, repeat, cycle
text = "wwworldggggreattecchemggpwwwzaz"
n = 3
c = cycle[chain[repeat[0, n], repeat[1, n]]]
res = ["".join[g] for _, g in groupby[text, lambda x: next[c]]]
print[res]
Output:
['www', 'orl', 'dgg', 'ggr', 'eat', 'tec', 'che', 'mgg', 'pww', 'wza', 'z']
answered Jul 23, 2021 at 23:08
TigerTV.ruTigerTV.ru
1,0382 gold badges14 silver badges33 bronze badges
These answers are all nice and working and all, but the syntax is so cryptic... Why not write a simple function?
def SplitEvery[string, length]:
if len[string]