The Python Oracle

How to take the first N items from a generator or list?

Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Hypnotic Puzzle3

--

Chapters
00:00 Question
00:20 Accepted answer (Score 684)
01:22 Answer 2 (Score 146)
01:32 Answer 3 (Score 56)
02:19 Answer 4 (Score 47)
02:55 Thank you

--

Full question
https://stackoverflow.com/questions/5234...

Question links:
[linq]: /questions/tagged/linq

Accepted answer links:
[itertools.islice()]: http://docs.python.org/library/itertools...

Answer 3 links:
[@Shaikovsky's answer]: https://stackoverflow.com/a/26186228/429...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #list #generator

#avk47



ACCEPTED ANSWER

Score 738


Slicing a list

top5 = array[:5]
  • To slice a list, there's a simple syntax: array[start:stop:step]
  • You can omit any parameter. These are all valid: array[start:], array[:stop], array[::step]

Slicing a generator

import itertools
top5 = itertools.islice(my_list, 5) # grab the first five elements
  • You can't slice a generator directly in Python. itertools.islice() will wrap an object in a new slicing generator using the syntax itertools.islice(generator, start, stop, step)

  • Remember, slicing a generator will exhaust it partially. If you want to keep the entire generator intact, perhaps turn it into a tuple or list first, like: result = tuple(generator)




ANSWER 2

Score 155


import itertools

top5 = itertools.islice(array, 5)



ANSWER 3

Score 52


In my taste, it's also very concise to combine zip() with xrange(n) (or range(n) in Python3), which works nice on generators as well and seems to be more flexible for changes in general.

# Option #1: taking the first n elements as a list
[x for _, x in zip(xrange(n), generator)]

# Option #2, using 'next()' and taking care for 'StopIteration'
[next(generator) for _ in xrange(n)]

# Option #3: taking the first n elements as a new generator
(x for _, x in zip(xrange(n), generator))

# Option #4: yielding them by simply preparing a function
# (but take care for 'StopIteration')
def top_n(n, generator):
    for _ in xrange(n):
        yield next(generator)



ANSWER 4

Score 22


The answer for how to do this can be found here

>>> generator = (i for i in xrange(10))
>>> list(next(generator) for _ in range(4))
[0, 1, 2, 3]
>>> list(next(generator) for _ in range(4))
[4, 5, 6, 7]
>>> list(next(generator) for _ in range(4))
[8, 9]

Notice that the last call asks for the next 4 when only 2 are remaining. The use of the list() instead of [] is what gets the comprehension to terminate on the StopIteration exception that is thrown by next().