如果是linq,我会
var top5 = array.Take(5);
如何用Python做到这一点?
如果是linq,我会
var top5 = array.Take(5);
如何用Python做到这一点?
你是指前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)
切片列表
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(发电机,启动,停止,步进) 记住,切割发电机会部分耗尽它。如果你想保持整个生成器的完整性,也许可以先将其转换为元组或列表,例如:
在我看来,将zip()与xrange(n)(或Python3中的range(n))结合使用也非常简洁,这在生成器上也很好,而且对于一般的更改似乎更灵活。
# 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)
使用itertools,您将获得另一个生成器对象,因此在大多数情况下,您将需要另一个步骤来获取前n个元素。至少有两种更简单的解决方案(在性能方面效率稍低,但非常方便)可以从生成器中获取元素:
使用列表推导式:
first_n_elements = [generator.next() for i in range(n)]
否则:
first_n_elements = list(generator)[:n]
其中n是你想要取的元素数量(例如,n=5表示前五个元素)。
如何做到这一点的答案可以在这里找到
>>> 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()而不是[]是为了让理解在next()抛出的StopIteration异常上终止。
@Shaikovsky的回答很好,但我想澄清两点。
[next(generator) for _ in range(n)]
这是最简单的方法,但如果生成器过早耗尽,则抛出StopIteration。
另一方面,以下方法最多返回n个项,这在许多情况下是可取的:
列表: [x for _, x in zip(范围(n),记录)]
发电机: (x for _, x in zip(range(n), records))