cpicanco - 1 year ago 71
Python Question

# Iterate over n successive elements of list (with overlapping)

The itertools python module implements some basic building blocks for iterators. As they say, "they form an iterator algebra". I was expecting, but I could not find a succinctly way of doing the following iteration using the module. Given a list of ordered real numbers, for example

``````a = [1.0,1.5,2.0,2.5,3.0]
``````

... return a new list (or just iterate) grouping by some
`n`
value, say
`2`

``````b = [(1.0,1.5),(1.5,2.0),(2.0,2.5),(2.5,3.0)]
``````

The way I found of doing this was as follows. First split the list in two, with evens and odds indexes:

``````even, odds = a[::2], a[1::2]
``````

Then construct the new list:

``````b = [(even, odd) for even, odd in zip(evens, odds)]
b = sorted(b + [(odd, even) for even, odd in zip(evens[1:], odds)])
``````

In essence, it is similar to a moving mean.

Is there a succinctly way of doing this (with or without itertools)?

For 2, you can just do

``````b = zip(a, a[1:])  # or list(zip(...)) on Python 3 if you really want a list
``````

For fixed n, the technique is similar:

``````# n = 4
b = zip(a, a[1:], a[2:], a[3:])
``````

For variable n, you could zip a variable number of slices, or (especially if the window size is close to the size of `a`) you could use slicing to take windows directly:

``````b = zip(*[a[i:] for i in xrange(n)])
# or
b = [tuple(a[i:i+n]) for i in xrange(len(a)-n)]
``````

If `a` is not a list, you could generalize the `pairwise` recipe from the itertools docs:

``````import copy
import itertools

def nwise(iterable, n):
# Make n tees at successive positions along the iterable.
tees = list(itertools.tee(iterable, 1))
for _ in xrange(n-1):
tees.append(copy.copy(tees[-1]))
next(tees[-1])

return zip(*tees)
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download