今天早些时候,我需要一次迭代一个字符串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
有更好/更清洁的方法吗?
答案 0 :(得分:46)
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
答案 1 :(得分:13)
也许这会更干净?
s = "+c-R+D-e"
for i in xrange(0, len(s), 2):
op, code = s[i:i+2]
print op, code
你也许可以写一个发电机来做你想做的事情,也许这会更加pythonic:)
答案 2 :(得分:5)
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
答案 3 :(得分:4)
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上,请使用document中izip_longest
的定义或将grouper函数更改为:
from itertools import izip, chain, repeat
def grouper(iterable, n, padvalue=None):
return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)
答案 4 :(得分:3)
发电机的绝佳机会。对于较大的列表,这将比压缩每个其他元素更有效。请注意,此版本还处理悬挂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异常。
答案 5 :(得分: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
答案 6 :(得分:2)
这种方法支持每个结果的任意数量的元素,懒惰地评估,输入iterable可以是生成器(不尝试索引):
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]
答案 7 :(得分:1)
>>> s = "+c-R+D-e"
>>> s
'+c-R+D-e'
>>> s[::2]
'+-+-'
>>>
答案 8 :(得分:1)
也许不是最有效的,但如果你喜欢正则表达式......
import re
s = "+c-R+D-e"
for op, code in re.findall('(.)(.)', s):
print op, code
答案 9 :(得分:0)
我遇到了类似的问题。结束这样的事情:
ops = iter("+c-R+D-e")
for op in ops
code = ops.next()
print op, code
我觉得它最具可读性。
答案 10 :(得分:0)
这是我的答案,我的眼睛有点清洁:
for i in range(0, len(string) - 1):
if i % 2 == 0:
print string[i:i+2]