phre
phre

Reputation: 9

Why does these two injects give the same output in ruby?

Why is the output the same?

First inject:

puts (3...10).inject(0) { |sum, x| (x % 3 == 0 || x % 5 == 0) ? sum + x : sum }
# => 23

Second inject:

puts (3...10).inject { |sum, x| (x % 3 == 0 || x % 5 == 0) ? sum + x : sum }
# => 23
# Why not 26?

I thought if there is no argument passed to it, inject uses the first element of the collection as initial value.

So the second inject should return the same value as this one:

puts (3...10).inject(3) { |sum, x| (x % 3 == 0 || x % 5 == 0) ? sum + x : sum }
# => 26

Upvotes: 0

Views: 66

Answers (2)

7stud
7stud

Reputation: 48599

#inject() with an argument:

result = (3...10).inject(0) do |sum, x| 
  puts "#{sum} <-- #{x}: sum = #{sum+x}"
  sum + x
end 

--output:--
0 <-- 3: sum = 3
3 <-- 4: sum = 7
7 <-- 5: sum = 12
12 <-- 6: sum = 18
18 <-- 7: sum = 25
25 <-- 8: sum = 33
33 <-- 9: sum = 42

...

#inject without an argument:

result = (3...10).inject() do |sum, x| 
  puts "#{sum} <-- #{x}: sum = #{sum+x}"
  sum + x
end 

--output:--
3 <-- 4: sum = 7
7 <-- 5: sum = 12
12 <-- 6: sum = 18
18 <-- 7: sum = 25
25 <-- 8: sum = 33
33 <-- 9: sum = 42

I always thought it takes the first element of the collection as initial value and still performs the first iteration

The first iteration uses arr[0] as the sum and arr[1] as the first x. When you don't provide an argument for inject(), it's equivalent to doing this:

data = (3...10).to_a
initial_sum = data.shift

data.inject(initial_sum) do |sum, x|
  puts "#{sum} <-- #{x}: sum = #{sum+x}"
  sum + x
end

--output:--
3 <-- 4: sum = 7
7 <-- 5: sum = 12
12 <-- 6: sum = 18
18 <-- 7: sum = 25
25 <-- 8: sum = 33
33 <-- 9: sum = 42

Upvotes: 1

user229044
user229044

Reputation: 239260

Why does these two injects give the same output in ruby?

... Because they're supposed to. They only differ by the addition of a 0.

I thought if there is no argument passed to it, inject uses the first element of the collection as initial value.

It does. But it doesn't duplicate it.

Your first example receives these numbers:

0, 3, 4, 5, 6, 7, 8, 9

Your second example receives these numbers:

3, 4, 5, 6, ...

Adding 0 to the beginning doesn't affect the result, they're both 23, not 26 as you claim.

Your 3rd example returns 26 because it receives these numbers:

3, 3, 4, 5, 6, ...

Upvotes: 5

Related Questions