从迭代器获取唯一值的快速方法


众所周知

,迭代器比常见的列表推导式表现出更好的性能:

In [8]: from random import random
In [10]: %timeit [random() for i in range(10000000)]
1 loops, best of 3: 883 ms per loop
In [11]: %timeit (random() for i in range(10000000))
10 loops, best of 3: 176 ms per loop

但是,当我尝试从迭代器中获取唯一值时,性能提升会消失:

In [12]: %timeit set([random() for i in range(10000000)])
1 loops, best of 3: 5.06 s per loop
In [13]: %timeit set((random() for i in range(10000000)))
1 loops, best of 3: 5.02 s per loop

我想知道是否有快速和通用的方法来获取可迭代对象的唯一值?(我知道numpy.unique,但我经常不得不使用字符串)。

正如@georg [11]所提到的,它的速度很快,因为它基本上什么都不做。

如果您使用的是 Python 2,range()会创建一个列表,而xrange()不会。这给出了:

In [1]: from random import random
In [2]: timeit set([random() for i in xrange(10000000)])
1 loops, best of 3: 6.11 s per loop
In [3]: timeit set(random() for i in xrange(10000000))
1 loops, best of 3: 5.61 s per loop

这显示了一点时间收益。无论如何,[3][2]的主要增益当然是记忆增益。

要回答您的问题,使用 set() 并确保不要在两者之间创建列表是从生成器获取唯一值的最佳(也是最 Pythonic)方法。

虽然set可以保证唯一性,但它会破坏顺序,使您的序列不那么随机,并且您不能保证拥有与您生成的项目一样多的项目。另一种方法是首先确保生成的所有项目都是唯一的,如 random.sample 所示:

sample(xrange(10000000), 60)

这是有效的xrange不仅是可迭代的,而且遵循序列协议(可索引且具有长度)。该问题涉及"获取可迭代对象的唯一值",这并不能很好地描述显示的示例的作用。也许如果我们知道任务是什么,就可以制定出更合适的答案。

最新更新