cpicanco - 1 year ago 42

Python Question

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`

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

Answer

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

Source (Stackoverflow)