Ter*_* Li 3 ruby reduce functional-programming inject
b1 = Time.now
puts (1..100000).inject(0) { |x, y| x + y }
a1 = Time.now
puts "Time for inject: #{a1 - b1}"
b2 = Time.now
sum = 0
(1..100000).each do |value|
sum += value
end
puts sum
a2 = Time.now
puts "Time for each: #{a2 - b2}"
Run Code Online (Sandbox Code Playgroud)
上面的Ruby代码比较了两种求和整数的方法.令我惊讶的是,更优雅的注入或减少方法胜过另一方.为什么会这样?人们为什么要使用低效注入或减少?只是因为它很优雅?
PS:感谢所有鼓舞人心的答案.我的目的是询问导致这些差异的幕后情况.
在这种情况下我会用一点点数学:
require "benchmark"
N = 5_000_000
Benchmark.bmbm do |bm|
bm.report "inject 1" do
(1..N).inject(0) { |x, y| x + y }
end
bm.report "inject 2" do
(1..N).inject(:+)
end
bm.report "each" do
sum = 0
(1..N).each do |value|
sum += value
end
end
bm.report "sum of finite arithmetic progression" do
((1 + N) * N) / 2
end
end
Run Code Online (Sandbox Code Playgroud)
结果是:
% ruby sum.rb
Rehearsal ------------------------------------------------------------------------
inject 1 0.500000 0.000000 0.500000 ( 0.507497)
inject 2 0.320000 0.000000 0.320000 ( 0.322675)
each 0.370000 0.000000 0.370000 ( 0.380504)
sum of finite arithmetic progression 0.000000 0.000000 0.000000 ( 0.000005)
--------------------------------------------------------------- total: 1.190000sec
user system total real
inject 1 0.500000 0.000000 0.500000 ( 0.507697)
inject 2 0.320000 0.000000 0.320000 ( 0.322323)
each 0.370000 0.000000 0.370000 ( 0.380307)
sum of finite arithmetic progression 0.000000 0.000000 0.000000 ( 0.000004)
%
Run Code Online (Sandbox Code Playgroud)
更好的数学总是更快:)
是的,代码可读性比微优化更重要.即使采用数百万元素的总和,差异也几乎不可察觉.此外,两种方法都是O(n),因此随着元素数量的增加,两种方法都不会明显优于另一种方法.
正如其他人所指出的那样,inject(:+)还是要快一点.即使它不是,选择最容易看到的那个,并且不要担心性能上的细微差别.这可能不是您的应用程序的瓶颈.
require "benchmark"
N = 5_000_000
Benchmark.bmbm do |bm|
bm.report "inject 1" do
(1..N).inject(0) { |x, y| x + y }
end
bm.report "inject 2" do
(1..N).inject(:+)
end
bm.report "each" do
sum = 0
(1..N).each do |value|
sum += value
end
end
end
Run Code Online (Sandbox Code Playgroud)
结果:
user system total real
inject 1 0.610000 0.000000 0.610000 ( 0.613080)
inject 2 0.370000 0.000000 0.370000 ( 0.370892)
each 0.570000 0.000000 0.570000 ( 0.568266)
Run Code Online (Sandbox Code Playgroud)