Мне нужен очень быстрый способ определить, содержит ли массив только целые числа со значением 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)
У вас есть несколько вариантов:
>> input.count(9)==input.size
=> true
или
>> input.select{|x| x != 9}.empty?
=> true
или решение, которое у вас было выше.
Это зацикливает массив и прерывает (возвращает false), когда найдено что-то не девятое.
[9,9,9,9,9,9,9,9,9,9,9,9].all?{|x| x == 9} # => true
РЕДАКТИРОВАТЬ: найти полный исходный код здесь. Опоры @nash для оригинальной идеи.
Итерация и возврат false, как только вы найдете элемент!= match.
def all_matches(arr, match)
arr.each do |element|
return false if element != match
end
true
end
С 2М случайными целыми числами от 0 до 9, 50 петель (n=50
):
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)
Код, используемый для генерации массива:
input = []
2000000.times { input << (rand*10).to_i }
С 2M 9 (все 9), 50 циклов:
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)
Я предполагаю, что вы имеете в виду input.uniq == [9]
как то, что вы действительно вернули мне false. Что вы хотите сказать быстрее? Нужен ли этот код очень быстро? Я думаю, что обнаружение быстрее, поскольку оно вернет первый элемент, соответствующий тесту:
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 })
Здесь еще один, который быстрее (метод count выше по-прежнему самый быстрый):
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
Связанный ответ здесь: fooobar.com/info/10945/...