使用linq我会

var top5 = array.Take(5);


如何使用Python做到这一点?

评论

列表和生成器都被问到这个问题令人困惑,这些应该是单独的问题

#1 楼

切片列表

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)


评论


还要注意itertools.islice将返回一个生成器。

–尼克T
2014年2月1日下午2:06

“如果要保持整个生成器完整无缺,也许先将其变成一个元组或列表”->在建立元组/列表的过程中,会不会耗尽整个生成器?

–lucid_dreamer
18-10-31在23:44

@lucid_dreamer是的,但是您有了一个新的数据结构(元组/列表),可以根据需要进行多次迭代

–达沃斯
18年11月29日在12:47

要在耗尽之前创建生成器的副本,您还可以使用itertools.tee,例如:generator,another_copy = itertools.tee(generator)

–马索德·卡里(Massood Khaari)
20年6月22日在19:12

#2 楼

import itertools

top5 = itertools.islice(array, 5)


评论


当没有None代替5时,它还具有返回整个数组的好属性。

–凯尔·麦克唐纳(Kyle McDonald)
16年1月12日在7:03

如果您想每次使用以下五个,则可以使用:iter(array)而不是array。

–yucer
16年6月15日在13:57

请注意,如果生成器用尽了这不会出错,那么生成器剩下的元素将很多,小于您的请求大小。

–雷神召唤师
17年5月23日在17:23

这是在以下方法中使用的方法:Itertools配方def take(n,iterable):返回列表(islice(iterable,n))

–亚伦·罗布森(Aaron Robson)
18年4月1日在18:43



#3 楼

以我的口味,将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)


#4 楼

@Shaikovsky的答案非常好(…,因为我发布了这个答案,所以进行了大量编辑),但是我想澄清几点。

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

这是最简单的方法但是,如果发电机过早用尽,则会抛出StopIteration


另一方面,以下方法返回n项,这在许多情况下是更可取的:

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

发电机:
(x for _, x in zip(range(n), records))

评论


少数几个对此答案不满意的人可以解释原因吗?

– Bede Constantinides
18-2-5在11:49



def take(num,iterable):return([元素_,zip中的elem(range(num),可迭代)])

–user-asterix
18年5月13日在18:50

上面的代码:循环访问可能是生成器或列表的可迭代对象,并从可迭代对象中返回最多n个元素。如果n大于或等于iterable中存在的项目数,则返回iterable中的所有元素。

–user-asterix
18年5月13日在19:13

对于列表x = [1,2,3,4,5,6],x [:20]也仅返回x中的6个元素。猜测x [:N]返回x的前N个元素,如果N> len(x),它将返回x。 python 3.6。

–詹森·目标(Jason Goal)
20-2-12在14:58

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


请注意,当仅剩2个电话时,最后一个电话要求下4个电话。使用list()而不是[]可以使理解理解终止于StopIteration抛出的next()异常。

评论


一些python版本的警告

–汤姆·黑尔
19年3月16日在10:30

澄清Tom的评论:在python 3.7中,您将获得RuntimeError(尽管绝对值得一读!)

– drevicko
19年7月2日在2:21

#6 楼

您是说前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)


评论


较小的不是第一位吗?

–贾德·迪亚斯(Jader Dias)
2011-3-8 15:32

导入heapq; top5 = heapq.nlargest(5,可迭代)

– Thijs van Dien
13-10-19在22:06

谢谢,值得编辑!

–托马斯
13-10-20在16:40

使用顺序而不是迭代。一些可迭代对象不支持索引。每个序列都是可迭代的,但是某些可迭代对象不是序列。

– jfs
2014-12-23 23:01



注意nlargest需要任何可迭代的,而不仅仅是序列。

–bfontaine
昨天

#7 楼

使用itertools,您将获得另一个生成器对象,因此在大多数情况下,您将需要采取前N个元素(N)的另一步骤。至少有两种更简单的解决方案(在性能方面效率稍低,但非常方便),可以从generator中使用这些元素:

使用列表理解:

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


否则:

first_N_element=list(generator)[:N]


其中N是您要采用的元素数(例如前五个元素N = 5)元素)。

#8 楼

这应该工作

top5 = array[:5] 


评论


@JoshWolff我没有拒绝这个答案,但是可能是因为这种方法不适用于生成器,除非它们定义了__getitem __()。例如,尝试运行itertools.count()[:5]或(x表示范围(10)中x的x)[:5],然后查看错误消息。但是,答案是列表的习惯用法。

– Undercat为Monica鼓掌
20 Jan 22 '13:00