在Ruby中,我正在构建一个构造并返回一个(可能很大)数组的方法,该数组不应包含任何重复元素。通过使用一个集合然后将其转换为数组,我会获得更好的性能吗?或者,在我返回之前,在我正在使用的数组上调用.uniq
会更好吗?或者使用&
将项目附加到数组而不是+=
呢?如果我确实使用了一个集合,那么在我放入集合的对象上没有<=>
方法会对性能产生影响吗? (如果你不确定,你知道一种测试方法吗?)
答案 0 :(得分:5)
真正的答案是:编写最具可读性和可维护性的代码,并在您显示它是瓶颈后才对其进行优化。如果您可以在is in linear time中找到算法,则无需对其进行优化。在这里很容易找到......
不太确定您建议使用哪种方法,但使用我的fruity
gem:
require 'fruity'
require 'set'
enum = 1000.times
compare do
uniq { enum.each_with_object([]){|x, array| array << x}.uniq }
set { enum.each_with_object(Set[]){|x, set| set << x}.to_a }
join { enum.inject([]){|array, x| array | [x]} }
end
# set is faster than uniq by 10.0% ± 1.0%
# uniq is faster than join by 394x ± 10.0
显然,像第三种方法一样构建中间数组是没有意义的。否则,它将不会产生很大的不同,因为你将在O(n)
;这是主要的事情。
顺便说一句,sets
,uniq
和Array#|
对您的对象使用eql?
和hash
,而不是<=>
。这些需要以理智的方式定义,因为默认情况下,对象永远不会eql?
,除非它们具有相同的object_id
(请参阅this question)
答案 1 :(得分:3)
您是否尝试过使用Benchmark库?测试通常很容易构建,并且能够正确反映它在特定版本的Ruby中的工作方式。