文字列を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
より明確にするために書くことさえできます。参加、圧縮、ループ、リストの理解はありません。隣り合った次の2つの文字を見つけるだけです。これは、人間の脳が正確にどのように考えるかです。モンティパイソンがまだ生きていたら、彼はこの方法が大好きです!
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()
ます。
>>> 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
or / andコンマを削除できないことに気付きました。私の編集者は,
:sの後に空白を追加することを提案しています
enumerate
は2つのイテラブルを返すため、それらを配置するには2つの場所が必要です。ただし、この場合、2番目の反復可能オブジェクトは何も必要ありません。
blah
アンダースコアまたはダブルアンダースコアを使用するのではなく、次を参照してください。stackoverflow.com
短い文字列の単純な再帰的な解決策:
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
ライブラリの4つのオプションを次に示します。
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']のようになります。