Можно ли разбить строку на каждый 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
если строка длинная, чтобы генерировать чанк по чанку.
'.'*n
чтобы было понятнее. Нет соединения, нет застегивания, нет петель, нет понимания списка; просто найдите следующие два символа рядом друг с другом, что именно так думает человеческий мозг. Если бы Монти Пайтон был еще жив, ему бы понравился этот метод!
flags=re.S
.
Для этого в 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.
'''
wrap
может не вернуть то, что запрашивается, если строка содержит пробел. например, wrap('0 1 2 3 4 5', 2)
возвращается ['0', '1', '2', '3', '4', '5']
(элементы удалены)
Еще один распространенный способ группировки элементов в группы n-длины:
>>> s = '1234567890'
>>> map(''.join, zip(*[iter(s)]*2))
['12', '34', '56', '78', '90']
Этот метод идет прямо из документов для zip()
.
zip(*[iter(s)]*2)
сложным для понимания, прочитайте, Как zip(*[iter(s)]*n)
работает в Python? ,
>>> map(''.join, zip(*[iter('01234567')]*5))
->['01234']
zip()
на itertools.zip_longest()
:map(''.join, zip_longest(*[iter(s)]*2, fillvalue=''))
Я думаю, что это короче и более читабельно, чем версия 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)))
Использование more-itertools из PyPI:
>>> from more_itertools import sliced
>>> list(sliced('1234567890', 2))
['12', '34', '56', '78', '90']
Вы можете использовать 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)
Эти функции экономят память и работают с любыми итерациями.
Попробуйте следующий код:
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)))
yield ''.join(piece)
его, чтобы он работал должным образом
>>> 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])]
print(line)
я получаю this is a line split into n characters
в качестве вывода. Может вам лучше поставить: line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]
? Исправьте это, и это хороший ответ :).
,blah
и почему это необходимо? Я заметил, что могу заменить blah
любым альфа-символом / символами, но не цифрами, и не могу удалить blah
запятую или / или. Мой редактор предлагает добавить пробел после ,
: s
enumerate
возвращает два итерируемых элемента, поэтому для их размещения необходимо два места. Но вам на самом деле не нужна вторая итерация для чего-либо в этом случае.
blah
предпочитать использовать подчеркивание или двойное подчеркивание, см .: stackoverflow.com/questions/5893163/…
Простое рекурсивное решение для короткой строки:
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)
, который более подробно иллюстрирует типичную модель «разделяй и властвуй» в рекурсивном подходе (хотя практически нет необходимости делать это таким образом)
Я застрял в том же сценарии.
Это сработало для меня
x="1234567890"
n=2
list=[]
for i in range(0,len(x),n):
list.append(x[i:i+n])
print(list)
Вывод
['12', '34', '56', '78', '90']
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
Это может быть достигнуто простым циклом for.
a = '1234567890a'
result = []
for i in range(0, len(a), 2):
result.append(a[i : i + 2])
print(result)
Вывод выглядит как ['12', '34', '56', '78', '90', 'a']