如何从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()抛出的StopIterationexception。

@谢科夫斯基的回答非常好,但我想澄清几点。

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