I believe that what you are looking for is already available as an itertools
recipe; even though pairwise
only allow you to return couples and not tuple of arbitrary length.
You will need to modify it so that:
tee
will return num
iterators;
- you advance each of these iterators by one more element than the previous one (see the
consume
recipe for that).
This can lead to the following code:
import itertools
def advance(iterator, step):
next(itertools.islice(iterator, step, step), None)
def tuplewize(iterable, size):
iterators = itertools.tee(iterable, size)
for position, iterator in enumerate(iterators):
advance(iterator, position)
return zip(*iterators)
Usage being:
>>> for t in tuplewize(lst, 4):
... print(t)
...
(10, 11, 12, 13)
(11, 12, 13, 26)
(12, 13, 26, 28)
However, you are using numpy
so we may come up with a better numpy approach:
numpy.roll
allows us to advance the nth element on top of the list;
numpy.stack
allows us to concatenate the rolled arrays into a single 2D array;
numpy.transpose
allows us to convert a "list of lists" into a "list of tuples".
Full code being:
import numpy as np
def tuplewize(array, size):
if size < 2:
return np.array([array])
stack = np.stack([np.roll(array, -i) for i in range(size)])
return np.transpose(stack)[:-size+1]
Usage being:
>>> tuplewise(lst, 4)
array([[10, 11, 12, 13],
[11, 12, 13, 26],
[12, 13, 26, 28]])
And as @Peilonrayz indicated in a comment, a third possibility is to use the more_itertools
package and its windowed
function which has extended capabilities; and as such more overhead, so depending on your needs it may or may not suit you.