我需要一种非常快速的方法来确定一个数组是否仅包含值为9
的整数。这是我当前的解决方案:
input = [9,9,9,9,9,9,9,9,9,9,9,9]
input.uniq == [9]
你能更快地完成吗?
我需要一种非常快速的方法来确定一个数组是否仅包含值为9
的整数。这是我当前的解决方案:
input = [9,9,9,9,9,9,9,9,9,9,9,9]
input.uniq == [9]
你能更快地完成吗?
require 'benchmark'
n = 50000
Benchmark.bm do |x|
x.report "uniq " do
n.times do
input = [9,9,9,9,9,9,9,9,9,9,9,9]
input.uniq == [9]
end
end
x.report "delete" do
n.times do
input = [9,9,9,9,9,9,9,9,9,9,9,9]
input.delete 9
input == []
end
end
x.report "count " do
n.times do
input = [9,9,9,9,9,9,9,9,9,9,9,9]
input.count(9)==input.size
end
end
x.report "select" do
n.times do
input = [9,9,9,9,9,9,9,9,9,9,9,9]
input.select{|x| x != 9}.empty?
end
end
x.report "detect" do
n.times do
input = [9,9,9,9,9,9,9,9,9,9,9,9]
input.detect { |i| i != 9 }.nil?
end
end
x.report "all? " do
n.times do
input = [9,9,9,9,9,9,9,9,9,9,9,9]
input.all?{|x| x == 9}
end
end
end
这是对以上答案以及我自己的一些基准测试结果。
user system total real
uniq 0.313000 0.000000 0.313000 ( 0.312500)
delete 0.140000 0.000000 0.140000 ( 0.140625)
count 0.079000 0.000000 0.079000 ( 0.078125)
select 0.234000 0.000000 0.234000 ( 0.234375)
detect 0.234000 0.000000 0.234000 ( 0.234375)
all? 0.219000 0.000000 0.219000 ( 0.218750)
如果 input = [1]+[9]*9
:
user system total real
uniq 0.328000 0.000000 0.328000 ( 0.328125)
delete 0.188000 0.000000 0.188000 ( 0.203125)
count 0.187000 0.000000 0.187000 ( 0.218750)
select 0.281000 0.016000 0.297000 ( 0.296875)
detect 0.203000 0.000000 0.203000 ( 0.203125)
all? 0.204000 0.000000 0.204000 ( 0.203125)
如果 input = [9]*9 + [1]
:
user system total real
uniq 0.313000 0.000000 0.313000 ( 0.328125)
delete 0.187000 0.000000 0.187000 ( 0.187500)
count 0.172000 0.000000 0.172000 ( 0.187500)
select 0.297000 0.000000 0.297000 ( 0.312500)
detect 0.313000 0.000000 0.313000 ( 0.312500)
all? 0.281000 0.000000 0.281000 ( 0.281250)
如果 input = [1,2,3,4,5,6,7,8,9]
:
user system total real
uniq 0.407000 0.000000 0.407000 ( 0.406250)
delete 0.125000 0.000000 0.125000 ( 0.125000)
count 0.125000 0.000000 0.125000 ( 0.125000)
select 0.218000 0.000000 0.218000 ( 0.234375)
detect 0.110000 0.000000 0.110000 ( 0.109375)
all? 0.109000 0.000000 0.109000 ( 0.109375)
x.report "detect" do
),并且还可以针对未通过测试的数组进行测试(例如 [1]+[9]*9
和 [9]*9+[1]
),那么这将是一个非常好的答案。 - Phrogz你有几个选项:
>> input.count(9)==input.size
=> true
或者>> input.select{|x| x != 9}.empty?
=> true
或者您之前提供的解决方案。
[9,9,9,9,9,9,9,9,9,9,9,9].all?{|x| x == 9} # => true
编辑:在此处查找完整的源代码here。感谢@nash提供的原始想法。
迭代并在找到一个不匹配的元素时立即返回false。
def all_matches(arr, match)
arr.each do |element|
return false if element != match
end
true
end
用户 系统 总计 实际 去重 5.230000 0.010000 5.240000 ( 5.219444) 计数 2.680000 0.010000 2.690000 ( 2.677923) 选择 7.580000 0.060000 7.640000 ( 7.634620) 检测 0.000000 0.000000 0.000000 ( 0.000068) 全部? 0.000000 0.000000 0.000000 ( 0.000046) 我的 0.000000 0.000000 0.000000 ( 0.000032) 删除 5.090000 0.020000 5.110000 ( 5.101290) 任意? 0.000000 0.000000 0.000000 ( 0.000041)用于生成数组的代码:
input = []
2000000.times { input << (rand*10).to_i }
2M 9(所有9)50次迭代结果如下:
用户 系统 总计 实际 去重 4.900000 0.000000 4.900000 ( 4.890030) 计数 0.350000 0.000000 0.350000 ( 0.351340) 选择 5.400000 0.010000 5.410000 ( 5.393489) 检测 6.720000 0.000000 6.720000 ( 6.685539) 是否全为9 6.070000 0.000000 6.070000 ( 6.061914) 查找我的 5.510000 0.010000 5.520000 ( 5.500186) 删除 1.080000 0.010000 1.090000 ( 1.084125) 是否存在 6.200000 0.000000 6.200000 ( 6.197529)
return false if arr.empty?
添加到我的方法中(这可能是必需的),它仍然比不执行此操作的 all?
方法表现更好。 - Olivier L.我猜你的意思是input.uniq == [9]
,因为实际上这个代码对我来说返回的是false。你所说的更快是什么意思?这段代码需要非常快地运行吗?我想detect更快,因为它会返回第一个符合测试条件的元素:
input = [9,9,9,9,9,9,9,9,9,9,9,9]
input.detect { |i| i != 9 }.nil?
input = [9,9,9,9,9,9,9,9,9,9,9,9]
!(input.any { |a| a != 9 })
这个很好用:
> array = ['apple', 'banana']
> includes = array.uniq.include? 'banana'
> => true
> array = ['apple', 'banana', 'apple']
> all_same_values = (array.uniq.length > 1) ? false : true
> => false
这里有另一种更快的方法(上面的计数方法仍然是最快的):
arr = [9,9,9,9,9,9,9,9,9,9,9,9]
arr.reject { |i| i==9 }.count == 0
还有一个速度稍慢的:
arr.inject(:&) == 9
require 'fruity'
compare do
count { arr.count(9) == arr.size }
uniq { arr.uniq == [9] }
bitwise_and { arr.inject(:&) == 9 }
reject { arr.reject { |i| i==9 }.count == 0 }
end
Running each test 8192 times. Test will take about 3 seconds.
count is faster than reject by 39.99999999999999% ± 10.0%
reject is faster than uniq by 10x ± 1.0
uniq is faster than bit_and by 30.000000000000004% ± 1.0%