Comment prendre les N premiers éléments d'un générateur ou d'une liste en Python? [dupliquer]

cette question a déjà une réponse ici:

  • comment obtenir les valeurs n suivantes d'un générateur dans une liste (python) 4 réponses

Avec linq je

var top5 = array.Take(5);

Comment faire avec Python?

211
demandé sur guaka 2011-03-08 17:53:10

8 réponses

trancher une liste

top5 = array[:5]
  • pour trancher une liste, il y a une syntaxe simple: array[start:stop:step]
  • vous pouvez omettre n'importe quel paramètre. Ils sont tous valables.: array[start:] , array[:stop] , array[::step]

couper une génératrice

 import itertools
 top5 = itertools.islice(my_list, 5) # grab the first five elements
  • vous ne pouvez pas couper un générateur directement en Python. itertools.islice() s'occupera de l'emballage un objet dans un nouveau générateur de tranchage utilisant la syntaxe itertools.islice(generator, start, stop, step)

  • rappelez-vous, couper une génératrice l'épuisera en partie. Si vous voulez garder la génératrice entière intacte, peut-être la transformer en un tuple ou la liste d'abord, comme: result = tuple(generator)

340
répondu lunixbochs 2016-06-11 04:17:57
import itertools

top5 = itertools.islice(array, 5)
97
répondu Jader Dias 2011-03-08 14:56:21

à mon goût, il est également très concis de combiner 'zip()' avec 'xrange(n)' (ou 'range(n)' en Python3), ce qui fonctionne bien sur les générateurs et semble être plus flexible pour les changements en général.

# 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)
29
répondu Shaikovsky 2018-02-01 19:46:27

la réponse de @Shaikovsky est excellente, mais je voulais clarifier quelques points.

[next(generator) for _ in range(n)]

c'est l'approche la plus simple, mais lance StopIteration si le générateur est prématurément épuisé.


d'autre part, les approches suivantes renvoient jusqu'à n éléments qui sont sans doute préférables dans la plupart des circonstances:

liste: [x for _, x in zip(range(n), records)]

générateur: (x for _, x in zip(range(n), records))

14
répondu Bede Constantinides 2016-11-06 19:40:27

la réponse à cette question se trouve ici

>>> 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]

noter que le dernier appel demande pour les 4 prochains alors qu'il ne reste que 2. L'utilisation du list() au lieu de [] est ce qui fait que la compréhension se termine sur l'exception StopIteration qui est lancée par next() .

9
répondu ebergerson 2017-05-23 12:34:47

voulez-vous dire le premier N articles, ou le N plus grand articles?

si vous voulez le premier:

top5 = sequence[:5]

cela fonctionne également pour les plus grands N articles, en supposant que votre séquence est triée dans l'ordre décroissant. (Votre exemple de LINQ semble le supposer aussi.)

si vous voulez le plus grand, et il n'est pas trié, la solution la plus évidente est de le trier d'abord:

l = list(sequence)
l.sort(reverse=True)
top5 = l[:5]

pour une solution plus performante, utilisez un Min-heap (merci Thijs):

import heapq
top5 = heapq.nlargest(5, sequence)
5
répondu Thomas 2015-10-20 19:14:13

avec itertools vous obtiendrez un autre objet générateur donc dans la plupart des cas vous aurez besoin d'une autre étape la prise des premiers éléments N ( N ). Il existe au moins deux solutions plus simples (un peu moins efficaces en termes de performances mais très pratiques) pour obtenir les éléments prêts à l'emploi à partir d'un generator :

à l'Aide de la liste de compréhension:

first_N_element=[generator.next() for i in range(N)]

sinon:

first_N_element=list(generator)[:N]

N est le nombre d'éléments que vous voulez prendre (par exemple N=5 pour les cinq premiers éléments).

3
répondu G M 2015-02-07 11:17:41

ça devrait marcher

top5 = array[:5] 
-4
répondu Bala R 2011-03-08 14:57:41