Iterate over a string 2 (or n) characters at a time in Python

后端 未结 12 1874
悲哀的现实
悲哀的现实 2020-11-30 07:27

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).

相关标签:
12条回答
  • 2020-11-30 08:01
    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)
    
    0 讨论(0)
  • 2020-11-30 08:05
    >>> s = "+c-R+D-e"
    >>> s
    '+c-R+D-e'
    >>> s[::2]
    '+-+-'
    >>>
    
    0 讨论(0)
  • 2020-11-30 08:06

    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 ops

    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.

    0 讨论(0)
  • 2020-11-30 08:07

    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 :)

    0 讨论(0)
  • 2020-11-30 08:07

    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]
    
    0 讨论(0)
  • 2020-11-30 08:07

    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]
    
    0 讨论(0)
提交回复
热议问题