My function needs two params(a,b) and if...break, which seems redundant. Can it be made prettier?

def slice_list(lst,num):
    Given a list or Numpy array,
    get consecutive tuples based on specific window. 
    rst = []
    for i,_ in enumerate(lst):
        a = i
        b = i + num
        if len(lst[a:b])<num:
    return rst


>>> lst = np.array([10, 11, 12, 13, 26, 28])
>>> slice_list(lst,4)
[(10, 11, 12, 13), (11, 12, 13, 26), (12, 13, 26, 28)]
  • 5
    \$\begingroup\$ This question is incomplete. To help reviewers give you better answers, please add sufficient context to your question. The more you tell us about what your code does and what the purpose of doing that is, the easier it will be for reviewers to help you. Questions should include a description of what the code does \$\endgroup\$ Jun 12, 2018 at 12:46
  • 1
    \$\begingroup\$ @MathiasEttinger I don't know why my code should give more context. What did I miss? I think others answers get my point. And I open your link but get 'Site not found' \$\endgroup\$
    – Jack
    Jun 13, 2018 at 0:55
  • \$\begingroup\$ Sorry, the link should be codereview.meta.stackexchange.com/q/1226/84718 Basically you don't explain the requirements of your function and thus we are left to guess at the specifications from the code and the example. How can we know that the code is correctly implemented, then? \$\endgroup\$ Jun 13, 2018 at 7:46

3 Answers 3


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.

  • 3
    \$\begingroup\$ There is a package that can replace tuplewize, more_itertools.windowed \$\endgroup\$
    – Peilonrayz
    Jun 12, 2018 at 14:39
  • \$\begingroup\$ @Peilonrayz your answer is great. \$\endgroup\$
    – Jack
    Jun 13, 2018 at 1:12

If you are passing in a list of 6 items, and you want sublists of length 4, the last list you can create starts at index 6-4=2. Instead of checking if the sublist is long enough, and breaking if it isn’t, generate only the valid list of starting indices:

for i in range( len(lst) - num + 1 ):
    rst.append( tuple( lst[i:i+num] ) )

Depending on your definition of pretty, and personal aesthetics:

rst = [ tuple( lst[i:i+num] ) for i in range( len(lst) - num + 1 ) ]

Comments about your code in no particular order:

  • You throw away a value from enumerate, I would instead use range.
  • You do an if statement every time you loop and because of this you need the a and b variables.
  • I think size is a better variable name then num.

Code after my comments:

def slice_list2(lst,size):
    if size > len(lst):
        return []
    rst = []
    for i in range(0,len(lst)-size+1):
    return rst

But I think this is a optimal place to use list comprehensions. So I would implement it something like this:

def slice_list3(lst,size):
    return [tuple(lst[x:x+size]) for x in range(0,len(lst)-size+1)]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.