Fastest method to see if all elements in an array have a particular value
我需要一个非常快速的方法来确定一个数组是否只包含值为
1 2 | input = [9,9,9,9,9,9,9,9,9,9,9,9] input.uniq == [9] |
你能快点吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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 |
它是上述答案和一些我的答案的基准。
1 2 3 4 5 6 7 | 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 2 3 4 5 6 7 | 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) |
如果
1 2 3 4 5 6 7 | 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 | 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) |
您有几个选择:
1 2 | >> input.count(9)==input.size => true |
或
1 2 | >> input.select{|x| x != 9}.empty? => true |
或者你上面的解决方案。
这将循环数组并中断(当发现非9的内容时返回false)。
1 | [9,9,9,9,9,9,9,9,9,9,9,9].all?{|x| x == 9} # => true |
编辑:在这里找到完整的源代码。向@nash提供原始想法的支持。
一找到元素就迭代并返回false!=匹配。
1 2 3 4 5 6 | def all_matches(arr, match) arr.each do |element| return false if element != match end true end |
对于0到9之间的2 m随机整数,50个循环(
1 2 3 4 5 6 7 8 9 | user system total real uniq 5.230000 0.010000 5.240000 ( 5.219444) count 2.680000 0.010000 2.690000 ( 2.677923) select 7.580000 0.060000 7.640000 ( 7.634620) detect 0.000000 0.000000 0.000000 ( 0.000068) all? 0.000000 0.000000 0.000000 ( 0.000046) mine 0.000000 0.000000 0.000000 ( 0.000032) delete 5.090000 0.020000 5.110000 ( 5.101290) any? 0.000000 0.000000 0.000000 ( 0.000041) |
用于生成数组的代码:
1 2 | input = [] 2000000.times { input << (rand*10).to_i } |
2米9秒(全部9秒),50圈:
1 2 3 4 5 6 7 8 9 | user system total real uniq 4.900000 0.000000 4.900000 ( 4.890030) count 0.350000 0.000000 0.350000 ( 0.351340) select 5.400000 0.010000 5.410000 ( 5.393489) detect 6.720000 0.000000 6.720000 ( 6.685539) all? 6.070000 0.000000 6.070000 ( 6.061914) mine 5.510000 0.010000 5.520000 ( 5.500186) delete 1.080000 0.010000 1.090000 ( 1.084125) any? 6.200000 0.000000 6.200000 ( 6.197529) |
这很有效:
1 2 3 | > array = ['apple', 'banana'] > includes = array.uniq.include? 'banana' > => true |
此外,通过扩展,我们可以检查所有值是否相同,而不知道它们是什么:
1 2 3 | > array = ['apple', 'banana', 'apple'] > all_same_values = (array.uniq.length > 1) ? false : true > => false |
相关答案:https://stackoverflow.com/a/1986398/1886534
这是另一个更快的方法(上面的计数方法仍然是最快的):
1 2 | arr = [9,9,9,9,9,9,9,9,9,9,9,9] arr.reject { |i| i==9 }.count == 0 |
还有一个稍微慢一点的:
1 | arr.inject(:&) == 9 |
以下是"果味"宝石对比:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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% |
也许是最慢的,但这就是我想到的
1 2 | input = [9,9,9,9,9,9,9,9,9,9,9,9] !(input.any { |a| a != 9 }) |
我想你的意思是"以东十一号"(0),因为你所得到的对我来说是假的。"更快"是什么意思?这个代码需要运行得很快吗?我认为检测速度更快,因为它将返回与测试匹配的第一个元素:
1 2 | input = [9,9,9,9,9,9,9,9,9,9,9,9] input.detect { |i| i != 9 }.nil? |