Iterate over pairs in a list (circular fashion) in Python

前端 未结 13 1836
醉酒成梦
醉酒成梦 2020-12-01 01:14

The problem is easy, I want to iterate over each element of the list and the next one in pairs (wrapping the last one with the first).

I\'ve thought about two unpyth

相关标签:
13条回答
  • 2020-12-01 01:56

    I, as always, like tee:

    from itertools import tee, izip, chain
    
    def pairs(iterable):
        a, b = tee(iterable)
        return izip(a, chain(b, [next(b)]))
    
    0 讨论(0)
  • 2020-12-01 01:57

    I'd do it like this (mostly because I can read this):

    class Pairs(object):
        def __init__(self, start):
            self.i = start
        def next(self):
            p, p1 = self.i, self.i + 1
            self.i = p1
            return p, p1
        def __iter__(self):
            return self
    
    if __name__ == "__main__":
        x = Pairs(0)
        y = 1
        while y < 20:
            print x.next()
            y += 1
    

    gives:

    (0, 1)
    (1, 2)
    (2, 3)
    (3, 4)
    (4, 5)
    (5, 6)
    (6, 7)
    (7, 8)
    (8, 9)
    
    0 讨论(0)
  • 2020-12-01 01:59

    This infinitely cycles, for good or ill, but is algorithmically very clear.

    from itertools import tee, cycle
    
    def nextn(iterable,n=2):
        ''' generator that yields a tuple of the next n items in iterable.
        This generator cycles infinitely '''
        cycled = cycle(iterable)
        gens = tee(cycled,n)
    
        # advance the iterators, this is O(n^2)
        for (ii,g) in zip(xrange(n),gens):
            for jj in xrange(ii):
                gens[ii].next()
    
        while True:
            yield tuple([x.next() for x in gens])
    
    
    def test():
        data = ((range(10),2),
            (range(5),3),
            (list("abcdef"),4),)
        for (iterable, n) in data:
            gen = nextn(iterable,n)
            for j in range(len(iterable)+n):
                print gen.next()            
    
    
    test()
    

    gives:

    (0, 1)
    (1, 2)
    (2, 3)
    (3, 4)
    (4, 5)
    (5, 6)
    (6, 7)
    (7, 8)
    (8, 9)
    (9, 0)
    (0, 1)
    (1, 2)
    (0, 1, 2)
    (1, 2, 3)
    (2, 3, 4)
    (3, 4, 0)
    (4, 0, 1)
    (0, 1, 2)
    (1, 2, 3)
    (2, 3, 4)
    ('a', 'b', 'c', 'd')
    ('b', 'c', 'd', 'e')
    ('c', 'd', 'e', 'f')
    ('d', 'e', 'f', 'a')
    ('e', 'f', 'a', 'b')
    ('f', 'a', 'b', 'c')
    ('a', 'b', 'c', 'd')
    ('b', 'c', 'd', 'e')
    ('c', 'd', 'e', 'f')
    ('d', 'e', 'f', 'a')
    
    0 讨论(0)
  • 2020-12-01 02:00

    To answer your question about solving for the general case:

    import itertools
    
    def pair(series, n):
        s = list(itertools.tee(series, n))
        try:
            [ s[i].next() for i in range(1, n) for j in range(i)]
        except StopIteration:
            pass
        while True:
            result = []
            try:
                for j, ss in enumerate(s):
                    result.append(ss.next())
            except StopIteration:
                if j == 0:
                    break
                else:
                    s[j] = iter(series)
                    for ss in s[j:]:
                        result.append(ss.next())
            yield result
    

    The output is like this:

    >>> for a in pair(range(10), 2):
    ...     print a
    ...
    [0, 1]
    [1, 2]
    [2, 3]
    [3, 4]
    [4, 5]
    [5, 6]
    [6, 7]
    [7, 8]
    [8, 9]
    [9, 0]
    >>> for a in pair(range(10), 3):
    ...     print a
    ...
    [0, 1, 2]
    [1, 2, 3]
    [2, 3, 4]
    [3, 4, 5]
    [4, 5, 6]
    [5, 6, 7]
    [6, 7, 8]
    [7, 8, 9]
    [8, 9, 0]
    [9, 0, 1]
    
    0 讨论(0)
  • 2020-12-01 02:03
    [(i,(i+1)%len(range(10))) for i in range(10)]
    

    replace range(10) with the list you want.

    In general "circular indexing" is quite easy in python; just use:

    a[i%len(a)] 
    
    0 讨论(0)
  • 2020-12-01 02:05

    Even shorter version of Fortran's zip * range solution (with lambda this time;):

    group = lambda t, n: zip(*[t[i::n] for i in range(n)])
    
    group([1, 2, 3, 3], 2)
    

    gives:

    [(1, 2), (3, 4)]
    
    0 讨论(0)
提交回复
热议问题