Earlier today I needed to iterate over a string 2 characters at a time for parsing a string formatted like \"+c-R+D-E\"
(there are a few extra letters).
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
requires Python 2.6( or higher). If on Python 2.4 or 2.5, use the definition for izip_longest
from the document or change the grouper function to:
from itertools import izip, chain, repeat
def grouper(iterable, n, padvalue=None):
return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)
>>> s = "+c-R+D-e"
>>> s
'+c-R+D-e'
>>> s[::2]
'+-+-'
>>>
Great opportunity for a generator. For larger lists, this will be much more efficient than zipping every other elemnent. Note that this version also handles strings with dangling 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
edit: minor rewrite to avoid ValueError exceptions.
Maybe this would be cleaner?
s = "+c-R+D-e"
for i in xrange(0, len(s), 2):
op, code = s[i:i+2]
print op, code
You could perhaps write a generator to do what you want, maybe that would be more pythonic :)
This approach support an arbitrary number of elements per result, evaluates lazily, and the input iterable can be a generator (no indexing is attempted):
import itertools
def groups_of_n(n, iterable):
c = itertools.count()
for _, gen in itertools.groupby(iterable, lambda x: c.next() / n):
yield gen
Any left-over elements are returned in a shorter list.
Example usage:
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]
Here's my answer, a little bit cleaner to my eyes:
for i in range(0, len(string) - 1):
if i % 2 == 0:
print string[i:i+2]