我有一个对象数组。 我想根据对象的某些属性在数组中找到一个对象。
我能做到
array.detect {|x| x.name=="some name"}
或者我可以做
ind=array.index {|x| x.name=="some name"}
array[ind] unless ind.nil?
有没有理由选择其中一个?
答案 0 :(得分:1)
如果您不想找到您要搜索的对象的索引值,我建议detect
。它将使您无需在访问阵列之前进行nil
检查。
从性能的角度来看,我认为它具有相对可比性,但这也可以帮助您做出决定。这将需要Niels B.在评论中提到的基准测试。
答案 1 :(得分:0)
如果要在集合中查找元素,请务必使用为快速检索而创建的集合。数组不是为此而制作的,除非您正在制作堆栈或队列,否则它们也不是特别方便。
以下是一些代码,用于展示使用find
,detect
或其他常规基于数组的方法提高存储/检索速度的方法:
require 'fruity'
require 'digest'
class Foo
attr_reader :var1, :var2
def initialize(var1, var2)
@var1, @var2 = var1, var2
end
end
START_INT = 1
START_CHAR = 'a'
END_INT = 10
END_CHAR = 'z'
START_MD5 = Digest::MD5.hexdigest(START_INT.to_s + START_CHAR)
END_MD5 = Digest::MD5.hexdigest(END_INT.to_s + END_CHAR)
ary = []
hsh = {}
hsh2 = {}
START_INT.upto(END_INT) do |i|
(START_CHAR .. END_CHAR).each do |j|
foo = Foo.new(i, j)
ary << foo
hsh[[i, j]] = foo
hsh2[Digest::MD5.hexdigest(i.to_s + j)] = foo
end
end
compare do
array_find {
ary.find { |a| (a.var1 == START_INT) && (a.var2 == START_CHAR) }
ary.find { |a| (a.var1 == END_INT) && (a.var2 == END_CHAR) }
}
hash_access_with_array {
hsh[[START_INT, START_CHAR]]
hsh[[END_INT, END_CHAR]]
}
hash_access_with_digest {
hsh2[START_MD5]
hsh2[END_MD5]
}
end
结果是:
Running each test 16384 times. Test will take about 17 seconds.
hash_access_with_digest is faster than hash_access_with_array by 10x ± 1.0
hash_access_with_array is faster than array_find by 16x ± 1.0
有三种不同的测试,我正在寻找数组ary
中的第一个和最后一个元素,以及哈希中的相应对象。查找数组中第一个和最后一个元素的结果将是该搜索的平均时间。为了比较,我在哈希中搜索相同的对象。
如果我们对该对象所在的数组索引有一些预先了解,那么从数组中检索对象会更快,但这就是问题,并且使另一个容器跟踪该信息会比使用哈希更慢
答案 2 :(得分:0)
亲自看看!
require 'benchmark'
array = (1..1000000).to_a
Benchmark.bmbm do |x|
x.report("#index for 1") {
array.index(1)
}
x.report("#detect 1") {
array.detect { |i| i == 1 }
}
x.report("#index for 500k") {
array.index(500000)
}
x.report("#detect 500k") {
array.detect { |i| i == 500000 }
}
x.report("#index for 1m") {
array.index(1000000)
}
x.report("#detect 1m") {
array.detect { |i| i == 1000000 }
}
end
将上面的代码放在一个文件中,然后使用ruby <file>
忽略顶部块,即排练,底部块看起来应该是这样的:
user system total real
#index for 1 0.000005 0.000002 0.000007 ( 0.000004)
#detect 1 0.000007 0.000002 0.000009 ( 0.000006)
#index for 500k 0.003274 0.000049 0.003323 ( 0.003388)
#detect 500k 0.029870 0.000200 0.030070 ( 0.030872)
#index for 1m 0.005866 0.000009 0.005875 ( 0.005880)
#detect 1m 0.059819 0.000520 0.060339 ( 0.061340)
在我的Mac和Ruby 2.5.0上运行时,数字似乎表明#detect
比#index
慢了一个数量级。