Reputation: 1621
I'm new to ruby and was going though a piece of code
scope_value = {"tickets_scope"=>"1", "changes_scope"=>"8", "solutions_scope"=>"15"}
scope_value.values.map { |i| 2** i.to_i }.inject(0, :|)
I realised
scope_value.values.map {|i| 2** i.to_i }.sum
does the the same thing as well
In terms of functionality doesn't both lines of code do the same thing. Is there any advantage to using sum over the other in terms of performance.
Upvotes: 2
Views: 195
Reputation: 369428
They do mean the same thing, but only because you don't use Float
s and only because you don't have a Range
.
At least in some versions of some Ruby implementations, sum
has some optimizations and specializations that inject
and +
can't have because they are much more general. For example, in YARV, the current implementation of the various variations of sum
is almost 200 lines, and includes the following optimizations
Enumerable#sum
, when applied to an Enumerable<Float>
, uses the Kahan-Babuška balancing compensated summation algorithm to prevent floating point accuracy errors from accumulating during the summationRange#sum
, when applied to a Range<Integer>
uses the well-known closed-form formula: (end - start + 1) * (end + start) / 2
end is thus independent of the size of the range any only depends on the length of the numbers involvedThe price we pay for this is that sum
may ignore monkeypatched versions of each
or +
.
Upvotes: 1
Reputation: 230296
In terms of functionality doesn't both lines of code do the same thing.
Yes, these two snippets produce identical results.
Does inject starting from 0 mean the same as sum
No, not at all. In fact, 0
is irrelevant here. You can omit it and still get the same result.
scope_value.values.map { |i| 2** i.to_i }.inject(:|)
Operations in these two snippets are very different. They only produce the same result because of special shape of your data. Which is "each number has only one bit set and no two numbers have the same bit set". Violate this rule and see results diverge.
BTW, before we had .sum
, we used to emulate it with .inject(:+)
. This does the same thing (when used on integer arrays)
Upvotes: 5