pythonrubyenumerableequivalent

Python Equivalent to Ruby's #each_cons?


Is there a Pythonic equivalent to Ruby's #each_cons?

In Ruby you can do this:

array = [1,2,3,4]
array.each_cons(2).to_a
=> [[1,2],[2,3],[3,4]]

Solution

  • For such things, itertools is the module you should be looking at:

    from itertools import tee, izip
    
    def pairwise(iterable):
        "s -> (s0,s1), (s1,s2), (s2, s3), ..."
        a, b = tee(iterable)
        next(b, None)
        return izip(a, b)
    

    Then:

    >>> list(pairwise([1, 2, 3, 4]))
    [(1, 2), (2, 3), (3, 4)]
    

    For an even more general solution, consider this:

    def split_subsequences(iterable, length=2, overlap=0):
        it = iter(iterable)
        results = list(itertools.islice(it, length))
        while len(results) == length:
            yield results
            results = results[length - overlap:]
            results.extend(itertools.islice(it, length - overlap))
        if results:
            yield results
    

    This allows arbitrary lengths of subsequences and arbitrary overlapping. Usage:

    >> list(split_subsequences([1, 2, 3, 4], length=2))
    [[1, 2], [3, 4]]
    >> list(split_subsequences([1, 2, 3, 4], length=2, overlap=1))
    [[1, 2], [2, 3], [3, 4], [4]]