使用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
评论
列表和生成器都被问到这个问题令人困惑,这些应该是单独的问题