Pythonic list slicing with variable step size?

Viewed 958

To frame the question, let's assume I've got the following list in Python, where X is some arbitrarily large natural number:

l = [1, 2, 3, 4, 5, 6, 7, ... X]

And I want to slice it such that I take the first, second, third, fifth, eighth, etc. elements of the list, abiding by the Fibonacci sequence. E.g. an operation akin to:

l_prime = [l[0], l[1], l[2], l[4], l[7], l[11], ...]

I'm comfortable with Python indexing notation, of l[start:end:step_size], and I'm wondering if there's a way to index Python lists within this notational paradigm with a step size that varies after each index is added to my new sliced list. Or, would I need to use some other technique to solve the prior problem I posed?

3 Answers

If you can use numpy this is really easy.

l = np.array([1, 2, 3, 4, ..., X])
fibs = np.array([0, 1, 2, 4, 7])
print(l[fibs])

If you want to retrieve multiple elements from the list you can use the function itemgetter():

from operator import itemgetter

lst = [1, 2, 3, 4, 5, 6, 7, 8]
ind = [0, 0, 1, 2, 4, 7] 

itemgetter(*ind)(lst)
# (1, 1, 2, 3, 5, 8)

You can first write a generator that gives you the fibonacci numbers:

def fibs():
    prev1 = 1
    prev2 = 2
    yield prev1
    yield prev2
    while True:
            prev1 += prev2
            prev2 += prev1
            yield prev1
            yield prev2

And then you can use list comprehension to map each of the fibonacci numbers fib to l[fib - 1]:

import itertools
result = [l[fib - 1] for fib in itertools.takewhile(lambda x: x <= len(l), fibs())]
Related