Можно ли разбить строку на каждый n-й символ?
Например, предположим, у меня есть строка, содержащая следующее:
'1234567890'
Как мне сделать так, чтобы это выглядело так:
['12','34','56','78','90']
Можно ли разбить строку на каждый n-й символ?
Например, предположим, у меня есть строка, содержащая следующее:
'1234567890'
Как мне сделать так, чтобы это выглядело так:
['12','34','56','78','90']
>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range(0, len(line), n)]
['12', '34', '56', '78', '90']
Просто чтобы завершить, вы можете сделать это с помощью регулярного выражения:
>>> import re
>>> re.findall('..','1234567890')
['12', '34', '56', '78', '90']
Для нечетного числа символов вы можете сделать это:
>>> import re
>>> re.findall('..?', '123456789')
['12', '34', '56', '78', '9']
Вы также можете сделать следующее, чтобы упростить регулярное выражение для более длинных кусков:
>>> import re
>>> re.findall('.{1,2}', '123456789')
['12', '34', '56', '78', '9']
И вы можете использовать re.finditer
, если строка длинная, чтобы сгенерировать чанк за чанк.
Для этого в Python уже есть встроенная функция.
>>> from textwrap import wrap
>>> s = '1234567890'
>>> wrap(s, 2)
['12', '34', '56', '78', '90']
Вот что говорит документация для упаковки:
>>> 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.
'''
Другой распространенный способ группировки элементов в группы n-длины:
>>> s = '1234567890'
>>> map(''.join, zip(*[iter(s)]*2))
['12', '34', '56', '78', '90']
Этот метод поступает прямо из документов для zip()
.
Я думаю, что это короче и более читаемо, чем версия itertools:
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)))
Мне нравится это решение:
s = '1234567890'
o = []
while s:
o.append(s[:2])
s = s[2:]
Используя more-itertools из PyPI:
>>> from more_itertools import sliced
>>> list(sliced('1234567890', 2))
['12', '34', '56', '78', '90']
Использование лямбда:
split_string = lambda x, n: [x[i:i+n] for i in range(0, len(x), n)]
s = '1234567890'
split_string(s,2)
['12', '34', '56', '78', '90']
Вы можете использовать рецепт itertools
grouper()
из itertools
:
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)
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)
Эти функции экономят память и работают с любыми итерациями.
Здесь мое решение:
def split_every(n, s):
return [ s[i:i+n] for i in xrange(0, len(s), n) ]
print split_every(2, "1234567890")
Попробуйте использовать следующий код:
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)))
>>> 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']
Попробуй это:
s='1234567890'
print([s[idx:idx+2] for idx,val in enumerate(s) if idx%2 == 0])
Выход:
['12', '34', '56', '78', '90']
Как всегда, для тех, кто любит один лайнер
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])]
more_itertools.sliced
ранее . Вот еще четыре варианта из more_itertools
:
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)]
Каждый из последних вариантов производит следующий вывод:
['12', '34', '56', '78', '90']
Документация для обсуждаемых опций: grouper
, chunked
, windowed
, split_after
У меня есть этот код, который я использую всякий раз, когда мне нужно это делать:
def split_string(n, st):
lst = [""]
for i in str(st):
l = len(lst) - 1
if len(lst[l]) < n:
lst[l] += i
else:
lst += [i]
return lst
print(split_string(3, "test_string."))
Где:
n
- длина каждого элемента спискаst
- это строка, которую нужно разделитьlst
- это версия списка st
i
- текущий символ, используемый в st
l
- это длина последнего элемента спискаПростое рекурсивное решение для короткой строки:
def split(s, n):
if len(s) < n:
return []
else:
return [s[:n]] + split(s[n:], n)
print(split('1234567890', 2))
Или в такой форме:
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)
который более подробно иллюстрирует типичную модель "разделяй и властвуй" в рекурсивном подходе (хотя практически нет необходимости делать это таким образом)
Одна возможность - использовать регулярные выражения:
import re
re.findall("\w{3}", your_string)
Spooky one – попытался придумать еще один ответ:
def split(s, chunk_size):
a = zip(*[s[i::chunk_size] for i in range(chunk_size)])
return [''.join(t) for t in a]
print(split('1234567890', 1))
print(split('1234567890', 2))
print(split('1234567890', 3))
Выход
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
['12', '34', '56', '78', '90']
['123', '456', '789']
def split(s, n):
"""
Split string every nth character
Parameters
----------
s: string
n: value of nth
"""
new_list = []
for i in range(0, len(s), n):
new_list.append(s[i:i+n])
return new_list
print(split('1234567890', 2))
Я знаю, что этот вопрос старый, но это самый короткий способ сделать это. Я знаю:
def split_every_n(S, n):
return [S[i*n:(i+1)*n] for i in range(len(S) / n)]
Это, однако, предполагает, что длина вашей строки кратно n. В противном случае вам придется проложить его.
Это может быть немного яснее
##Define your string
mystring = '1234567890'
##Define your starting index
start = 0
##Define the end of your index for the first slice
end = 2
##Create an empty list
mylist =[]
##While the slice of characters without white space has something in it keep going
while len(mystring[start:end])>0:
##Add to the list
mylist.append(mystring[start:end])
##Move the index up for the begining and ending of the slice
start+=2
end+=2
def splitstr(oldstr,n):
start = 0
end = n
newlist =[]
while len(oldstr[start:end])>0:
newlist.append(oldstr[start:end])
start+=n
end+=n
return newlist
print(splitstr('1234567890', 2))
Вот еще одно решение для более общего случая, когда куски не имеют одинаковой длины. Если длина равна 0, возвращается вся оставшаяся часть.
data
- последовательность, подлежащая разделению; fieldsize
- это кортеж со списком длины поля.
def fieldsplit(data=None, fieldsize=()):
tmpl=[];
for pp in fieldsize:
if(pp>0):
tmpl.append(line[:pp]);
line=line[pp:];
else:
tmpl.append(line);
break;
return tuple(tmpl);
Я использую это:
list(''.join(s) for s in zip(my_str[::2], my_str[1::2]))
или вы можете использовать любой другой n
номер вместо 2
.
def display(list):
for i in list: #To display the strings
print(i)
#Take a group of strings from keyboard
print('Enter strings separated by comma: ')
list = [x for x in input().split(",")]
#call display() and pass the list
display(list)
#output
karthik, siva, raman, inban
Enter strings separated by comma:
karthik
siva
raman
inban
Этот вопрос напоминает мне метод Perl 6 .comb(n)
. Он разбивает строки на n
-sized кусков. (Там больше, чем это, но я опущу детали.)
Достаточно просто реализовать похожую функцию в Python3 в качестве лямбда-выражения:
comb = lambda s,n: [s[i:i+n] for i in range(0,len(s),n)]
Тогда вы можете назвать это так:
comb('1234567', 2) # returns ['12', '34', '56', '7']
Эта функция comb()
также будет работать со списками (для создания списка списков):
comb(['cat', 'dog', 'bird'], 2) # returns [['cat', 'dog'], ['bird']]