今日の初めに、"+c-R+D-E"
のような形式の文字列を解析するために、一度に2文字ずつ文字列を反復処理する必要がありました(余分な文字がいくつかあります)。
私はこれでうまくいきました、しかしそれは醜く見えます。それは自明ではないと感じたので、私はそれが何をしているのかコメントすることになりました。ほとんどPythonicのようですが、完全ではありません。
# Might not be exact, but you get the idea, use the step
# parameter of range() and slicing to grab 2 chars at a time
s = "+c-R+D-e"
for op, code in (s[i:i+2] for i in range(0, len(s), 2)):
print op, code
これを行うためのより良い/よりクリーンな方法はありますか?
Dunnoはクリーナーについてですが、別の方法があります:
for (op, code) in Zip(s[0::2], s[1::2]):
print op, code
コピーなしバージョン:
from itertools import izip, islice
for (op, code) in izip(islice(s, 0, None, 2), islice(s, 1, None, 2)):
print op, code
たぶんこれはもっときれいでしょうか?
s = "+c-R+D-e"
for i in xrange(0, len(s), 2):
op, code = s[i:i+2]
print op, code
あなたはおそらくあなたが望むことをするためにジェネレータを書くことができます、多分それはよりPythonicになるでしょう:)
Triptych このより一般的なソリューションに影響を与えました:
def slicen(s, n, truncate=False):
assert n > 0
while len(s) >= n:
yield s[:n]
s = s[n:]
if len(s) and not truncate:
yield s
for op, code in slicen("+c-R+D-e", 2):
print op,code
from itertools import izip_longest
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return izip_longest(*args, fillvalue=fillvalue)
def main():
s = "+c-R+D-e"
for item in grouper(s, 2):
print ' '.join(item)
if __name__ == "__main__":
main()
##output
##+ c
##- R
##+ D
##- e
izip_longest
にはPython 2.6(以上)が必要です。オンの場合Python 2.4または2.5の場合、izip_longest
の定義を使用します- document またはgrouper関数を次のように変更:
from itertools import izip, chain, repeat
def grouper(iterable, n, padvalue=None):
return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)
発電機にとって絶好の機会。より大きなリストの場合、これは他のすべての要素を圧縮するよりもはるかに効率的です。このバージョンは、ダングリングop
sの文字列も処理することに注意してください
def opcodes(s):
while True:
try:
op = s[0]
code = s[1]
s = s[2:]
except IndexError:
return
yield op,code
for op,code in opcodes("+c-R+D-e"):
print op,code
編集:ValueError例外を回避するための小さな書き直し。
他の答えはn = 2でうまくいきますが、一般的なケースではこれを試すことができます:
def slicen(s, n, truncate=False):
nslices = len(s) / n
if not truncate and (len(s) % n):
nslices += 1
return (s[i*n:n*(i+1)] for i in range(nslices))
>>> s = '+c-R+D-e'
>>> for op, code in slicen(s, 2):
... print op, code
...
+ c
- R
+ D
- e
>>> for a, b, c in slicen(s, 3):
... print a, b, c
...
+ c -
R + D
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: need more than 2 values to unpack
>>> for a, b, c in slicen(s,3,True):
... print a, b, c
...
+ c -
R + D
このアプローチは、結果ごとに任意の数の要素をサポートし、遅延評価します。入力反復可能オブジェクトはジェネレーターにすることができます(インデックス付けは試行されません)。
import itertools
def groups_of_n(n, iterable):
c = itertools.count()
for _, gen in itertools.groupby(iterable, lambda x: c.next() / n):
yield gen
残った要素は短いリストで返されます。
使用例:
for g in groups_of_n(4, xrange(21)):
print list(g)
[0, 1, 2, 3]
[4, 5, 6, 7]
[8, 9, 10, 11]
[12, 13, 14, 15]
[16, 17, 18, 19]
[20]
>>> s = "+c-R+D-e"
>>> s
'+c-R+D-e'
>>> s[::2]
'+-+-'
>>>
多分最も効率的ではないかもしれませんが、正規表現が好きなら...
import re
s = "+c-R+D-e"
for op, code in re.findall('(.)(.)', s):
print op, code
私は同様の問題に遭遇しました。このようなことをやめました:
ops = iter("+c-R+D-e")
for op in ops
code = ops.next()
print op, code
最も読みやすいと感じました。
これが私の答えです、私の目には少しきれいです:
for i in range(0, len(string) - 1):
if i % 2 == 0:
print string[i:i+2]
pip
のインストールを検討してください more_itertools
、これはすでに chunked
実装とともに他の役立つツールとともに出荷されています。
import more_itertools
for op, code in more_itertools.chunked(s, 2):
print(op, code)
出力:
+ c
- R
+ D
- e