如何从生成器或列表中取出前 N 个项目?[重复]
- 2025-02-05 13:24:00
- admin 原创
- 96
问题描述:
和林克我会
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)
解决方案 2:
import itertools
top5 = itertools.islice(array, 5)
解决方案 3:
@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))
解决方案 4:
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)
解决方案 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()
而不是使得推导式在抛出的异常[]
上终止。StopIteration
`next()`
解决方案 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)
解决方案 7:
您itertools
将获得另一个生成器对象,因此在大多数情况下,您将需要另一个步骤来获取第一个n
元素。至少有两种更简单的解决方案(性能方面效率稍低,但非常方便)可以从中获得可供使用的元素generator
:
使用列表理解:
first_n_elements = [generator.next() for i in range(n)]
否则:
first_n_elements = list(generator)[:n]
其中n
是要获取的元素数量(例如,前五个元素为 n=5)。
解决方案 8:
这应该有效
top5 = array[:5]