¿Cómo tomar los primeros N elementos de un generador o lista en Python? [duplicar]
Esta pregunta ya tiene una respuesta aquí:
Con linq yo
var top5 = array.Take(5);
¿Cómo hacer esto con Python?
8 answers
Cortar una lista
top5 = array[:5]
- Para cortar una lista, hay una sintaxis simple:
array[start:stop:step]
- puede omitir cualquier parámetro. Todos estos son válidos:
array[start:]
,array[:stop]
,array[::step]
Cortar un generador
import itertools
top5 = itertools.islice(my_list, 5) # grab the first five elements
No puedes dividir un generador directamente en Python.
itertools.islice()
envolverá un objeto en un nuevo generador de corte usando la sintaxisitertools.islice(generator, start, stop, step)
Recuerde, cortar un generador lo agotará parcialmente. Si quieres mantener todo el generador intacto, tal vez convertirlo en una tupla o lista primero, como:
result = tuple(generator)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-11 04:17:57
import itertools
top5 = itertools.islice(array, 5)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-08 14:56:21
En mi gusto, también es muy conciso combinar 'zip()' con 'xrange(n)' (o 'range(n)' en Python3), que también funciona bien en 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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-01 19:46:27
La respuesta de@Shaikovsky es excelente, pero quería aclarar un par de puntos.
[next(generator) for _ in range(n)]
Este es el enfoque más simple, pero arroja StopIteration
si el generador se agota prematuramente.
Por otro lado, los siguientes enfoques devuelven hasta n
items which is arguably preferable in most circumstances:
Lista:
[x for _, x in zip(range(n), records)]
Generador:
(x for _, x in zip(range(n), records))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-06 19:40:27
La respuesta para 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 pide los siguientes 4 cuando solo quedan 2. El uso de list()
en lugar de []
es lo que hace que la comprensión termine en la excepción StopIteration
que es lanzada por next()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:47
¿Te refieres a los primeros N elementos, o los N más grandes elementos?
Si quieres el primero:
top5 = sequence[:5]
Esto también funciona para los N elementos más grandes, suponiendo que su secuencia esté ordenada en orden descendente. (Su ejemplo de LINQ parece asumir esto también.)
Si quieres el más grande, y no está ordenado, la solución más obvia es ordenarlo primero:
l = list(sequence)
l.sort(reverse=True)
top5 = l[:5]
Para una solución más eficiente, utilice un min-heap (Thijs gracias):
import heapq
top5 = heapq.nlargest(5, sequence)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-20 19:14:13
Con itertools
obtendrá otro objeto generador por lo que en la mayoría de los casos necesitará otro paso para tomar los primeros N elementos (N
). Hay al menos dos soluciones más simples (un poco menos eficientes en términos de rendimiento, pero muy útiles) para obtener los elementos listos para usar de un generator
:
Usando la comprensión de lista:
first_N_element=[generator.next() for i in range(N)]
De lo contrario:
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).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-07 11:17:41
Esto debería funcionar
top5 = array[:5]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-08 14:57:41