Jak pobrać pierwsze N elementów z generatora lub listy w Pythonie? [duplikat]

To pytanie ma już odpowiedź tutaj:

With linq I would

var top5 = array.Take(5);

Jak to zrobić z Pythonem?

Author: guaka, 2011-03-08

8 answers

Wycinanie listy

top5 = array[:5]
  • aby pokroić listę, istnieje prosta składnia: array[start:stop:step]
  • można pominąć dowolny parametr. Wszystkie są ważne: array[start:], array[:stop], array[::step]

Cięcie generatora

 import itertools
 top5 = itertools.islice(my_list, 5) # grab the first five elements
  • Nie można wyciąć generatora bezpośrednio w Pythonie. itertools.islice() owinie obiekt w nowym generatorze krojenia używając składni itertools.islice(generator, start, stop, step)

  • Pamiętaj, że przecięcie generatora spowoduje jego częściowe wyczerpanie. Jeśli chcesz zachować całą generator nienaruszony, może najpierw przekształcić go w krotkę lub listę, jak: result = tuple(generator)

 340
Author: lunixbochs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-11 04:17:57
import itertools

top5 = itertools.islice(array, 5)
 97
Author: Jader Dias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-08 14:56:21

W moim guście jest również bardzo zwięzłe łączenie 'zip()' z 'xrange (N) '(lub' range (N) ' w Python3), które działa dobrze na generatorach i wydaje się być bardziej elastyczne dla zmian w ogóle.

# 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
Author: Shaikovsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-01 19:46:27

@Shaikovsky odpowiedź jest doskonała, ale chciałem wyjaśnić kilka punktów.

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

Jest to najprostsze podejście, ale rzuca StopIteration, jeśli generator jest przedwcześnie wyczerpany.


Z drugiej strony, następujące podejścia zwracają do n przedmioty, które są prawdopodobnie preferowane w większości sytuacji:

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

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

 14
Author: Bede Constantinides,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-06 19:40:27

Odpowiedź jak to zrobić można znaleźć tutaj

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

Zauważ, że ostatnie połączenie prosi o następne 4, gdy pozostały tylko 2. Użycie list() zamiast {[2] } jest tym, co sprawia, że zrozumienie kończy się na StopIteration wyjątku, który jest wyrzucany przez next().

 9
Author: ebergerson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:47

Masz na myśli pierwsze N elementy, czy N największe elementy?

Jeśli chcesz pierwszy:

top5 = sequence[:5]

Działa to również dla największych N pozycji, zakładając, że Twoja sekwencja jest sortowana w porządku malejącym. (Twój przykład LINQ wydaje się również zakładać to.)

Jeśli chcesz największy, a nie jest posortowany, najbardziej oczywistym rozwiązaniem jest najpierw posortowanie:

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

Aby uzyskać bardziej wydajne rozwiązanie, użyj sterty min (dzięki Thijs):

import heapq
top5 = heapq.nlargest(5, sequence)
 5
Author: Thomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-20 19:14:13

Z itertools uzyskasz kolejny obiekt generatora, więc w większości przypadków będziesz potrzebował kolejnego kroku, aby wykonać pierwsze N elementów (N). Istnieją co najmniej dwa prostsze rozwiązania (nieco mniej wydajne pod względem wydajności, ale bardzo poręczne), aby przygotować elementy do użycia z generator:

Użycie rozumienia listy:

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

Inaczej:

first_N_element=list(generator)[:N]

Gdzie N jest liczbą elementów, które chcesz wziąć (np. N = 5 dla pierwszych pięciu elementów).

 3
Author: G M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-07 11:17:41

To powinno zadziałać

top5 = array[:5] 
 -4
Author: Bala R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-08 14:57:41