Чи можна розділити рядок кожного 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']
Ось що говорить docstring для обгортання:
>>> 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)))
Використання більше-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)
щоб вона працювала так, як очікувалося: eval.in/813878
>>> 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)
, що більш наочно ілюструє типовий зразок поділу та підкорення в рекурсивному підході (хоча практично не потрібно робити це таким чином)
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
Цього можна досягти простим для циклу.
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']