【发布时间】:2015-02-21 02:56:43
【问题描述】:
我想知道我应该将我的数据结构作为一个集合还是一个列表。大多数情况下我会做集合操作,但最后我需要对它进行排序。
我想知道是否应该先将集合设为列表,然后使用sorted(list(my_set)),还是直接对集合进行排序sorted(my_set)。可以说,我可能会考虑一个通用的“列出”阶段,因为在那个时间点有一个有序的迭代可能是有意义的。
所以我决定测试一下,希望列表更快。
基准测试:
import time
def sorter(x):
t1 = time.time()
for i in range(1000000):
sorted(x)
return time.time() - t1
数据:
one = range(1000)
a1 = list(one)
b1 = set(one)
sorter(a1)
# time: 16.5 s
sorter(b1)
# time: 20.7 s
然后我意识到这可能与元素已经就位这一事实有关,并记住了this amazing question & answer。
然后,我尝试了一些随机数据:
two = numpy.random.randint(1, 1000, 1000)
a2 = list(two)
b2 = set(two)
有了结果:
sorter(a2)
# time: 4min 49s
sorter(b2)
# time: 18.9 s
差别很大,怎么回事?
奖励:它甚至在一分钟的时间出现,sorted(set(a_list)) 比sorted(a_list) 快得多。
确实,在第二种情况下,可能会有重复的被过滤掉,从而加快排序。
【问题讨论】:
-
一个集合将主要按哈希键排序,在整数的情况下,哈希键就是值本身。 Python 中的 Timsort 算法擅长识别已经排序的序列。
-
b2 可能会明显短于 a2。这并不能解释整个效果,但重要的是要注意,当您为这两个操作计时时,您没有使用可比较的输入大小
-
@PascalvKooten 我不是基准测试专家,但我希望如果您想更公平地对集合和列表进行时间排序,您可以随机排列一个范围(1000),然后取结果作为集合或列表。这至少会让你从同一个 N 开始。
-
@PascalvKooten 你想要一个随机的 unique 元素样本。
numpy.random.randint不保证这一点。 -
根据我的测试,使用非平凡的数据类型(例如
(int, int))会逆转此处看到的趋势,尽管使用中间集只会增加轻微的低效率(~10%)。我怀疑为什么对整数使用中间集更快的原因是因为集合构造过程会自动将每个整数以正确的顺序(或非常接近)而不对它们进行排序,因为 Python 使用的微不足道的哈希.
标签: list python-2.7 sorting set