在Python中,每次迭代字符串2(或n)个字符

在Python中,每次迭代字符串2(或n)个字符,python,iteration,Python,Iteration,今天早些时候,我需要一次迭代一个字符串2个字符,以便解析一个格式类似“+c-R+D-E”(还有几个额外的字母)的字符串 我最终得到了这个,这很有效,但看起来很难看。我最后评论了它在做什么,因为它感觉不明显。这几乎像是蟒蛇,但不完全是 # 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"

今天早些时候,我需要一次迭代一个字符串2个字符,以便解析一个格式类似
“+c-R+D-E”
(还有几个额外的字母)的字符串

我最终得到了这个,这很有效,但看起来很难看。我最后评论了它在做什么,因为它感觉不明显。这几乎像是蟒蛇,但不完全是

# 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

有更好/更干净的方法吗?

也许这样更干净

>>> s = "+c-R+D-e"
>>> s
'+c-R+D-e'
>>> s[::2]
'+-+-'
>>>
s = "+c-R+D-e"
for i in xrange(0, len(s), 2):
    op, code = s[i:i+2]
    print op, code
你也许可以写一个生成器来做你想做的事情,也许那会更像python:)

izip_longest
需要Python 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)

我不知道清洁剂,但还有另一种选择:

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

其他答案对于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
def切片n(s,n,truncate=False):
n许可证=len(s)/n
如果未截断和(长度%n):
n许可证+=1
范围内i的返回(s[i*n:n*(i+1)](n许可证))
>>>s='+c-R+D-e'
>>>对于op,切片中的代码(s,2):
...     打印操作,代码
... 
+c
-R
+D
-e
>>>对于切片中的a、b、c(s、3):
...     打印a、b、c
... 
+c-
研发
回溯(最近一次呼叫最后一次):
文件“”,第1行,是否在中?
ValueError:需要2个以上的值才能解包
>>>对于切片中的a、b、c(s、3、True):
...     打印a、b、c
... 
+c-
研发

对于发电机来说,这是一个绝佳的机会。对于较大的列表,这将比压缩其他元素更有效。请注意,此版本还处理悬挂
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异常。

启发了这一更通用的解决方案:

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

也许不是最有效的,但是如果你喜欢正则表达式

import re
s = "+c-R+D-e"
for op, code in re.findall('(.)(.)', s):
    print op, code

此方法支持每个结果的任意数量的元素,计算是惰性的,输入iterable可以是生成器(不尝试索引):

任何剩余的元素都会在较短的列表中返回

用法示例:

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]

我遇到了类似的问题。最后做了这样的事情:

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

    print op, code

我觉得这是最具可读性的。

以下是我的答案,对我的眼睛来说稍微干净一点:

范围(0,len(string)-1)中的i的
:
如果i%2==0:
打印字符串[i:i+2]

请考虑安装
pip
安装,它已经随实现和其他有用工具一起提供:

import more_itertools 

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

+ c
- R
+ D
- e

@Richard,可能在第2行遗漏了a“)”?可能重复+1简单,并且它适用于任意n(如果在len(s)不是n的倍数时处理ValueError异常。少数边缘情况-始终引发ValueError:尝试操作码(“a1”)我真的很喜欢这一个…我只是希望它不要复制以进行迭代。如果字符串的字符数为奇数,zip方法将跳过最后一个字符。最佳答案,除了它重命名为
zip\u longest
range
也支持一个步骤;)--对于范围内的I(0,len(str),2):打印str[I:I+2]
import more_itertools 

for op, code in more_itertools.chunked(s, 2):
    print(op, code)
+ c
- R
+ D
- e