I have an array like:
["4|23", "1", "3|10", "2"]
I want to get the sum of the odd elements, i.e. 1 + 2 = 3, perhaps with inject
?
This is the response by Redis ZRANGE WITHSCORES for a sorted set. Ideally, I want to get the sum of the SCORES in a sorted set.
Thanks to everyone for your answers. All of them were really cool & enlightening.
I came up with an answer of my own. It's pretty straightforward:
sum = 0; gifts.each_with_index { |s, i| sum += s.to_i if i % 2 == 1 }; sum
I did a performance check:
require "benchmark"
MANY = 50000
gifts = [
"4|2323", "1",
"3|102343", "2",
"0|12330", "1",
"3|10234873", "2",
"5|2343225", "1",
"5|23423744", "1",
"2|987", "4",
"0|987345", "1",
"2|46593", "1",
"4|78574839", "3",
"3|4756848578", "1",
"3|273483", "3"
]
Benchmark.bmbm do |x|
x.report("each_with_index") { MANY.times { sum = 0; gifts.each_with_index { |s, i| sum += s.to_i if i % 2 == 1 }; sum } }
x.report("each_with_index") { MANY.times { sum = 0; gifts.each_with_index { |s, i| sum += s.to_i if i.odd? }; sum } }
x.report("values_at") { MANY.times { gifts.values_at(*(1..gifts.length).step(2)).inject(0) { |s, n| s += n.to_i } } }
x.report("each_slice") { MANY.times { gifts.each_slice(2).inject(0) { |i, (j,k)| i += k.to_i } } }
x.report("values_at") { MANY.times { gifts.values_at(*gifts.each_index.select { |i| i.odd? }).map(&:to_i).inject(&:+) } }
x.report("hash") { MANY.times { Hash[*gifts].values.map(&:to_i).reduce(:+) } }
end
Running the script above output the following on my Mac:
user system total real
each_with_index 0.300000 0.000000 0.300000 ( 0.305377)
each_with_index 0.340000 0.000000 0.340000 ( 0.334806)
values_at 0.370000 0.000000 0.370000 ( 0.371520)
each_slice 0.380000 0.000000 0.380000 ( 0.376020)
values_at 0.540000 0.000000 0.540000 ( 0.539633)
hash 0.560000 0.000000 0.560000 ( 0.560519)
Looks like my answer is the fastest. :-)