С linq Я бы
var top5 = array.Take(5);
Как это сделать с Python?
top5 = array[:5]
array[start:stop:step]
array[start:]
, array[:stop]
, array[::step]
import itertools
top5 = itertools.islice(my_list, 5) # grab the first five elements
Вы не можете нарезать генератор прямо на Python. itertools.islice()
перенесет объект в новый генератор среза, используя синтаксис itertools.islice(generator, start, stop, step)
Помните, что нарезка генератора частично исчерпает его. Если вы хотите, чтобы весь генератор оставался нетронутым, возможно, сначала переведите его в кортеж или список, например: result = tuple(generator)
import itertools
top5 = itertools.islice(array, 5)
В моем вкусе также очень кратким сочетать zip() с диапазоном (n), который хорошо работает и на генераторах, и, кажется, более гибкий для изменений в целом.
В Python 3 оба типа zip() и range() являются генераторами. В Python 2 вы можете получить верхние элементы для создания генератора.
# taking the first n elements as a list
[x for _, x in zip(range(n), generator)]
# or, alternatively
[next(generator) for _ in range(n)]
# taking the first n elements as a new generator
# (can work great in Python 3, since zip() and range() are generators)
(x for _, x in zip(range(n), generator))
# or yielding them by simply preparing a function
def top_n(n, generator):
for _ in range(n): yield next(generator)
@Ответ Шайковского отличный, но я хотел уточнить пару пунктов.
[next(generator) for _ in range(n)]
Это самый простой подход, но бросает StopIteration
, если генератор преждевременно исчерпан.
С другой стороны, следующие подходы возвращают элементы до n
, которые, возможно, предпочтительнее в большинстве случаев:
Список:
[x for _, x in zip(range(n), records)]
Генератор:
(x for _, x in zip(range(n), records))
Ответ на вопрос о том, как это сделать, можно найти здесь
>>> 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]
Обратите внимание, что последний вызов запрашивает следующие 4, когда осталось только 2. Использование list()
вместо []
- это то, что получает понимание для завершения в исключении StopIteration
, которое выбрано next()
.
Вы имеете в виду первые N элементов или N наибольших предметов?
Если вы хотите первый:
top5 = sequence[:5]
Это также работает для самых больших N элементов, предполагая, что ваша последовательность сортируется в порядке убывания. (Возможно, и ваш пример LINQ).
Если вам нужен самый большой и он не отсортирован, наиболее очевидным решением является его сортировка в первую очередь:
l = list(sequence)
l.sort(reverse=True)
top5 = l[:5]
Для более эффективного решения используйте мини-кучу (спасибо Thijs):
import heapq
top5 = heapq.nlargest(5, sequence)
С помощью itertools
вы получите еще один объект-генератор, поэтому в большинстве случаев вам понадобится еще один шаг: возьмите первые N элементов (N
). Есть как минимум два простых решения (немного менее эффективные с точки зрения производительности, но очень удобные), чтобы получить готовые элементы из generator
:
Использование списка:
first_N_element=[generator.next() for i in range(N)]
В противном случае:
first_N_element=list(generator)[:N]
Где N
- количество элементов, которые вы хотите принять (например, N = 5 для первых пяти элементов).
Это должно работать
top5 = array[:5]
Вы должны использовать срезы:
Попробуйте следующее:
>>> lst = [1,2,3,4,5]
>>> lst[:2]
[1, 2]
Требуется от индекса 0 к индексу 2.
Вы также можете делать такие вещи, как:
>>> lst = [1,2,3,4,5]
>>> lst[2:4]
[3, 4]