n番目の文字ごとに文字列を分割しますか?


回答:


550
>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range(0, len(line), n)]
['12', '34', '56', '78', '90']

35
これは、何らかの方法で畳み込まれていないので、本当に素晴らしい答えであるという事実は、あなたがその単純に簡単にする方法を覚えておくことができます
トレバー・ルドルフ

1
@TrevorRudolphそれはあなたが言うことを正確に行うだけです。上記の答えは実際には単なるforループですが、pythonで表現されます。また、「単純な」答えを覚えておく必要がある場合、それらを覚える方法は少なくとも数十万通りあります。電子メールにコピーして貼り付けます。覚えておきたいものを「役立つ」ファイルに保存する。必要なときに最新の検索エンジンを使用するだけ。(おそらく)すべてのWebブラウザでブックマークを使用する。など
dylnmc

1
第二に、それはあなた本気のように見えます。実際に複雑ではないので、あなたが真剣であることを私は実際に願っています。
dylnmc 2014年

1
私は真剣でした、私はエミュレーターのバイナリコンバーターでこのコードを使用しました。それはpythonic for loop haahaであることが好きでしたが、メソッドを楽しむ理由をさらに分析してくれてありがとう!
Trevor Rudolph

5
皮肉なことに、隠された意味を持たない方法で単語を使用しようとすると、多くの場合、複雑な文章になります。
deed02392 2015年

208

完全にするために、正規表現でこれを行うことができます:

>>> 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、文字列が長い場合は、チャンクごとにチャンクを生成するために使用できます。


3
これは断然最高の答えであり、トップに値するはずです。'.'*nより明確にするために書くことさえできます。参加、圧縮、ループ、リストの理解はありません。隣り合った次の2つの文字を見つけるだけです。これは、人間の脳が正確にどのように考えるかです。モンティパイソンがまだ生きていたら、彼はこの方法が大好きです!
jdk1.0 2018

これも適度に長い文字列の最も速い方法です:gitlab.com/snippets/1908857
Ralph Bolton

文字列に改行が含まれている場合、これは機能しません。これが必要flags=re.Sです。
Aran-Fey

ahhh .... regex ....なぜ私はそのXDを思いつかなかった
Mr PizzaGuy

148

このための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.
'''

2
print(wrap( '12345678'、3))は、文字列を3桁のグループに分割しますが、前ではなく後ろから始まります。結果:['123'、 '456'、 '78']
Atalanttore

2
'wrap'について学ぶのは興味深いですが、上記の質問とまったく同じではありません。文字列を固定数の文字に分割するのではなく、テキストを表示することを目的としています。
Oren

2
wrap文字列にスペースが含まれている場合、要求された内容が返されない場合があります。例:wrap('0 1 2 3 4 5', 2)リターン['0', '1', '2', '3', '4', '5'](要素は削除されます)
satomacoto

3
これは確かに質問に答えますが、スペースがあり、分割された文字でスペースを維持したい場合はどうなりますか?wrap()は、分割された文字のグループの直後にスペースがある場合、スペースを削除します
Iron Attorney

1
テキストをハイフンで分割する場合、これはうまく機能しません(引数として指定する数値は、実際には最大文字数であり、正確な文字数ではありません。つまり、ハイフンと空白で壊れます)。
MrVocabulary

81

要素をn長のグループにグループ化する別の一般的な方法:

>>> s = '1234567890'
>>> map(''.join, zip(*[iter(s)]*2))
['12', '34', '56', '78', '90']

このメソッドは、のドキュメントから直接来ていzip()ます。


2
[19]で:a = "hello world"; list(map( "" .join、zip(* [iter(a)] * 4)))結果を取得します['hell'、 'o wo']。
truease.com

16
誰かがzip(*[iter(s)]*2)理解するのが難しいと感じたら、Pythonでどのように機能zip(*[iter(s)]*n)するのですか?を読んでください
Grijesh Chauhan 2014

15
これは奇数の文字を考慮せず、単にそれらの文字を削除します:>>> map(''.join, zip(*[iter('01234567')]*5))->['01234']
Bjorn

3
また、文字の奇数を処理するには、単に置き換えるzip()itertools.zip_longest()map(''.join, zip_longest(*[iter(s)]*2, fillvalue=''))
パウロ・フレイタス

また役立つ:のドキュメントmaps()
winklerrr

58

これは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)))

7
しかし、実際には効率的ではありません。文字列に適用すると、コピーが多すぎます
Eric

1
また、seqがジェネレーターの場合も機能しません。これは、itertoolsバージョンが対応しているものです。そのOPがそれを要求したわけではありませんが、itertoolのバージョンがそれほど単純ではないことを批判するのは公平ではありません。
CryingCyclops 2017年

25

私はこの解決策が好きです:

s = '1234567890'
o = []
while s:
    o.append(s[:2])
    s = s[2:]


12

次のgrouper()レシピを使用できます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)

これらの関数はメモリ効率が高く、あらゆるイテラブルで機能します。


6

次のコードを試してください:

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)))

あなたの答えはOPの要件を満たしていません。yield ''.join(piece)期待どおりに機能させるために使用する必要があります:eval.in/813878
Paulo Freitas

5
>>> 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']

4

これを試して:

s='1234567890'
print([s[idx:idx+2] for idx,val in enumerate(s) if idx%2 == 0])

出力:

['12', '34', '56', '78', '90']

3

いつものように、ワンライナーを愛する人のために

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])]

これをPython Fiddleで実行すると、出力としてprint(line)取得さthis is a line split into n charactersれます。あなたはより良い置くかもしれません:line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]?これを修正し、それは良い答えです:)。
Google検索の内容

,blahとそれが必要な理由を説明できますか?blah数字ではなく任意の英字に置き換えることができ、blahor / andコンマを削除できないことに気付きました。私の編集者は,:sの後に空白を追加することを提案しています
toonarmycaptain 2017

enumerateは2つのイテラブルを返すため、それらを配置するには2つの場所が必要です。ただし、この場合、2番目の反復可能オブジェクトは何も必要ありません。
ダニエルF

1
blahアンダースコアまたはダブルアンダースコアを使用するのではなく、次を参照してください。stackoverflow.com
Andy Royal

2

短い文字列の単純な再帰的な解決策:

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)

、これは再帰的アプローチの典型的な分割統治パターンをより明示的に示しています(実際にはこのようにする必要はありません)。


2

私は同じ状況で立ち往生しました。

これは私のために働いた

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']

1

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']

議論のオプションのドキュメント:grouperchunkedwindowedsplit_after


0

これは、単純な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']のようになります。


2
このコードは質問に答えることがありますが、このコードが質問に答える理由や方法に関する追加のコンテキストを提供すると、長期的な価値が向上します。
β.εηοιτ.βε

2
これは同じソリューションです:stackoverflow.com/a/59091507/7851470
Georgy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.