37

今日の初めに、次のようにフォーマットされた文字列を解析するために、一度に2文字の文字列を反復処理する必要が"+c-R+D-E"ありました(余分な文字がいくつかあります)。

私はこれでうまくいきましたが、見た目は醜いです。それが自明ではないと感じたので、私はそれが何をしているのかコメントすることになりました。それはほとんど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

これを行うためのより良い/よりクリーンな方法はありますか?

4

13 に答える 13

55

クリーナーについてはわかりませんが、別の方法があります。

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
于 2009-07-22T01:39:53.347 に答える
16

多分これはもっときれいだろうか?

s = "+c-R+D-e"
for i in xrange(0, len(s), 2):
    op, code = s[i:i+2]
    print op, code

あなたはおそらくあなたが望むことをするためにジェネレータを書くことができます、多分それはもっとpythonicでしょう:)

于 2009-07-22T01:35:35.630 に答える
6
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_longestPython 2.6(以降)が必要です。Python 2.4または2.5の場合はizip_longestドキュメントのの定義を使用するか、grouper関数を次のように変更します。

from itertools import izip, chain, repeat
def grouper(iterable, n, padvalue=None):
    return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)
于 2009-07-22T01:36:58.000 に答える
6

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
于 2009-07-22T03:43:59.387 に答える
4

発電機にとって絶好の機会。より大きなリストの場合、これは他のすべての要素を圧縮するよりもはるかに効率的です。このバージョンは、ぶら下がっている文字列も処理することに注意してopください

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例外を回避するためのマイナーな書き直し。

于 2009-07-22T02:59:36.320 に答える
2

他の答えは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
于 2009-07-22T02:40:51.357 に答える
2

このアプローチは、結果ごとに任意の数の要素をサポートし、遅延評価を行い、反復可能な入力をジェネレーターにすることができます(インデックス付けは試行されません)。

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]
于 2013-10-31T06:00:27.547 に答える
2

pipをインストールすることを検討してください。これは、他の便利なツールと一緒に実装more_itertoolsがすでに付属しています。chunked

import more_itertools 

for op, code in more_itertools.chunked(s, 2):
    print(op, code)

出力:

+ c
- R
+ D
- e
于 2016-12-03T01:58:21.767 に答える
1
>>> s = "+c-R+D-e"
>>> s
'+c-R+D-e'
>>> s[::2]
'+-+-'
>>>
于 2009-07-22T01:28:28.260 に答える
1

おそらく最も効率的ではありませんが、正規表現が好きな場合は...

import re
s = "+c-R+D-e"
for op, code in re.findall('(.)(.)', s):
    print op, code
于 2009-07-22T05:10:23.487 に答える
1

これが私の答えです、私の目には少しきれいです:

for i in range(0, len(string) - 1):
    if i % 2 == 0:
        print string[i:i+2]
于 2014-04-22T06:21:50.697 に答える
0

私は同様の問題に遭遇しました。このようなことをやめました:

ops = iter("+c-R+D-e")
for op in ops
    code = ops.next()

    print op, code

一番読みやすいと感じました。

于 2014-04-01T22:53:01.443 に答える
0

私はこの単純なジェネレーターを作成しました:

def every_two(s):
    d = list(s)
    c = True
    for i in range(len(d)):
        if c:
            c = False
            yield d[i], d[i+1]
        else:
            c = True

文字列の長さが2で割り切れない場合は、IndexErrorが発生しますが、yieldステートメントをtryブロックでラップするだけで済みます。

于 2021-12-08T14:14:46.040 に答える