Ruby 查看数组中所有元素是否具有特定值的最快方法
我需要一种非常快速的方法来确定数组是否只包含值为Ruby 查看数组中所有元素是否具有特定值的最快方法,ruby,arrays,performance,Ruby,Arrays,Performance,我需要一种非常快速的方法来确定数组是否只包含值为9的整数。以下是我当前的解决方案: input = [9,9,9,9,9,9,9,9,9,9,9,9] input.uniq == [9] 你能做得更快吗?我想你的意思是input.uniq==[9],因为你实际上为我返回了false。你说的更快是什么意思?这段代码需要快速运行吗?我认为detect更快,因为它将返回与测试匹配的第一个元素: input = [9,9,9,9,9,9,9,9,9,9,9,9] input.detect { |i|
9
的整数。以下是我当前的解决方案:
input = [9,9,9,9,9,9,9,9,9,9,9,9]
input.uniq == [9]
你能做得更快吗?我想你的意思是
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.count(9)==input.size
=> true
或
或者您上面的解决方案。这将循环数组并在找到非9的内容时中断(返回false}
[9,9,9,9,9,9,9,9,9,9,9,9].all?{|x| x == 9} # => true
它是上述答案和我的一些答案的基准
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)
如果输入=[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)
如果输入=[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)
如果输入=[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)
编辑:查找完整的源代码。为@nash提供原始想法的道具
迭代并在找到元素!=匹配后立即返回false
def all_matches(arr, match)
arr.each do |element|
return false if element != match
end
true
end
对于从0到9的2M随机整数,50个循环(
n=50
):
用户系统总真实值
uniq 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.0000000.0000000.000000(0.000068)
全部?0.0000000.0000000.000000(0.000046)
矿山0.0000000.0000000.000000(0.000032)
删除5.090000 0.020000 5.110000(5.101290)
任何?0.0000000.0000000.000000(0.000041)
用于生成数组的代码:
input = []
2000000.times { input << (rand*10).to_i }
input=[]
2000000次{input也许是最慢的,但这就是我想到的
input = [9,9,9,9,9,9,9,9,9,9,9,9]
!(input.any { |a| a != 9 })
下面是另一个更快的方法(上面的计数方法仍然是最快的):
还有一个稍微慢一点:
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%
这很有效:
> array = ['apple', 'banana']
> includes = array.uniq.include? 'banana'
> => true
此外,通过扩展,我们可以检查所有值是否相同,而不知道它们是什么:
> array = ['apple', 'banana', 'apple']
> all_same_values = (array.uniq.length > 1) ? false : true
> => false
这里有一个相关的答案:,你的代码和我的代码,谢谢你提供了关于大括号的信息,我已经纠正了上面的例子。你的想象与实际的基准测试相比是微不足道的。谢谢,第一个是最快的(到目前为止:)),第二个是痛苦的缓慢。第一个是缓慢的,当你投入大量的投入。这里的其他解决方案会更快。你也能在元素都不同的情况下产生结果吗?在这种情况下,“全部”解决方案比“uniq”快。如果你给报告贴上标签,这将是一个非常好的答案(例如,x.report“detect”do
),并针对未通过测试的阵列进行测试(例如,[1]+[9]*9
和[9]*9+[1]
)。对这些结果求平均值是个好主意,因此人们不需要梳理四个基准时间表。除此之外,非常好!要正确回答这个问题,需要知道实际数组有多大,以及非9值的概率有多大。对于一种类型的输入,速度更快的解决方案可能是slo对其他人来说是正确的。很好的一点,数组可以非常大,超过2M个元素,九的概率是1/10;)然后听起来你想要优化的是拒绝非9值,这是la@steenslag的解决方案。一个完整的数组扫描是昂贵的。@bashman:你真的希望2M个元素都是相同的,任何元素都有10%的概率有一个给定的值吗?:)看起来人们忽略了我的答案,因为它有0票,尽管给出了best性能。将此注释放在此处以邀请人们查看。当输入非常大且可能包含非9值时,请快速。请注意,mine
基准测试结果是我的算法的结果。还请注意,如果将如果arr.empty返回false?
添加到我的方法中(这可能是必需的,也可能不是必需的),它的性能仍然比不这样做的all?
方法要好。我不明白为什么在上一个基准测试中计数速度如此之快。@steenslag:一定与此有关。还有另一个方法!:)请参阅我对比较基准测试的回答(我刚刚添加了您的方法,标记为any?
)。
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%
> array = ['apple', 'banana']
> includes = array.uniq.include? 'banana'
> => true
> array = ['apple', 'banana', 'apple']
> all_same_values = (array.uniq.length > 1) ? false : true
> => false