¿Cómo tomar los primeros N elementos de un generador o lista en Python?

Con linq lo haría

var top5 = array.Take(5); 

¿Cómo hacer esto con Python?

Cortar una lista

 top5 = array[:5] 
  • Para dividir una lista, hay una syntax simple: array[start:stop:step]
  • Puede omitir cualquier parámetro. Todos estos son válidos: array[start:] , array[:stop] , array[::step]

Cortando un generador

  import itertools top5 = itertools.islice(my_list, 5) # grab the first five elements 
  • No puedes cortar un generador directamente en Python. itertools.islice() envolverá un objeto en un nuevo generador de itertools.islice(generator, start, stop, step) utilizando la syntax itertools.islice(generator, start, stop, step)

  • Recuerde, cortar un generador lo agotará parcialmente. Si desea mantener todo el generador intacto, quizás conviértalo primero en una tupla o lista, como: result = tuple(generator)

 import itertools top5 = itertools.islice(array, 5) 

En mi gusto, también es muy conciso combinar ‘zip ()’ con ‘xrange (n)’ (o ‘range (n)’ en Python3), que también funciona bien en los generadores y parece ser más flexible para los cambios en 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) 

La respuesta de @ Shaikovsky es excelente ( … y está muy editada desde que publiqué esta respuesta ), pero quería aclarar un par de puntos.

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

Este es el enfoque más simple, pero lanza StopIteration si el generador se agota prematuramente.


Por otro lado, los siguientes enfoques devuelven hasta n elementos, lo que podría decirse que es preferible en la mayoría de las circunstancias:

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

Generador: (x for _, x in zip(range(n), records))

La respuesta sobre cómo hacer esto se puede encontrar aquí.

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

Observe que la última llamada solicita los siguientes 4 cuando solo quedan 2. El uso de la list() lugar de [] es lo que hace que la comprensión finalice en la excepción StopIteration que se produce al next() .

¿Te refieres a los primeros artículos N, o los artículos N más grandes ?

Si quieres lo primero:

 top5 = sequence[:5] 

Esto también funciona para los N elementos más grandes, asumiendo que su secuencia está ordenada en orden descendente. (Tu ejemplo de LINQ parece asumir esto también).

Si desea lo más grande, y no está ordenado, la solución más obvia es hacerlo primero:

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

Para una solución más eficiente, use un min-heap (gracias Thijs):

 import heapq top5 = heapq.nlargest(5, sequence) 

Con itertools obtendrá otro objeto generador, por lo que en la mayoría de los casos necesitará otro paso: tomar los primeros N elementos ( N ). Existen al menos dos soluciones más simples (un poco menos eficientes en términos de rendimiento pero muy útiles) para preparar los elementos de un generator :

Usando la lista de comprensión:

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

De otra manera:

 first_N_element=list(generator)[:N] 

Donde N es el número de elementos que desea tomar (por ejemplo, N = 5 para los primeros cinco elementos).

Esto debería funcionar

 top5 = array[:5]