如何从Python中的生成器或列表中获取前N个项目?
用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)
将对象包装在新的切片生成itertools.islice(generator, start, stop, step)
-
请记住,切片发生器将部分耗尽。 如果你想保持整个生成器完好无损,也许先把它变成一个元组或列表,如:
result = tuple(generator)
import itertools top5 = itertools.islice(array, 5)
在我的口味中,将zip()与range(n)结合起来也非常简洁,这对于生成器也很好,而且对于一般的变化似乎更加灵活。
在Python 3中,zip()和range()都是生成器。 在Python 2中,仍然可以生成顶层元素来创build生成器。
# 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)
如何做到这一点的答案可以在这里find
>>> 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()
而不是[]
的用法是理解终止在next()
抛出的StopIteration
exception。
@谢科夫斯基的回答非常好,但我想澄清几点。
[next(generator) for _ in range(n)]
这是最简单的方法,但如果发生器过早耗尽,则会引发StopIteration
。
另一方面,下面的方法返回n
项目,在大多数情况下可以说是可取的。
列表: [x for _, x in zip(range(n), records)]
生成器: (x for _, x in zip(range(n), records))
你的意思是前 N项,还是N项最大项?
如果你想要第一个:
top5 = sequence[:5]
这也适用于最大的N项,假设你的序列按降序排列。 (你的LINQ例子似乎也假设这一点。)
如果你想要的最大,而不是sorting,最明显的解决办法是先sorting:
l = list(sequence) l.sort(reverse=True) top5 = l[:5]
对于更高性能的解决scheme,请使用最小堆(谢谢Thijs):
import heapq top5 = heapq.nlargest(5, sequence)
使用itertools
您将获得另一个生成器对象,所以在大多数情况下,您将需要采取第一个N元素( N
)的另一个步骤。 至less有两个更简单的解决scheme(在性能方面效率稍低一点,但非常方便),以便从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]