.inject method. So I will try to demystify a method that (to me) epitomizes Ruby, yet baffles many that first encounter it.First, let's start with the basic concept. Here is some code you might find around in Ruby examples, etc., to demonstrate the purpose of
inject:
(1..10).inject(0) { |cumulative_sum, item| cumulative_sum + item } #=> 55
Let's dissect:
(1..10)is an inclusiveRange(if you don't know what aRangeis in Ruby...better read up here, as it is out of scope for this article) from 1 to 10 (inclusive).- Then because
RangeisEnumerable(again if you don't know whatEnumerablein Ruby means...read up about it here, again out of scope of this posting) it hasinjectavailable, so it bears remembering that it isn't just Arraysinjectwill work on. - We initially pass in 0 (yes, that's zero) as the argument to inject, which tells inject to start the "balance" at 0 (yes, zero again). Then it iterates through all the elements in the Range from 1 to 10 (inclusively remember because we used two dots not three) passing in the cumulative sum (or balance) and the current item into the block you define. The block we defined above is an expression that evaluates to an integer in this case.
- The result of this expression is now set to the cumulative_sum (or "balance") carried forward into the next iteration. So as we should have all learned in school Mathematics when getting to summation series', the cumulative sum of 1 through 10 is 55 (this is the result we get from inject from the above code - and not by accident either - this is exactly what
injectis all about).
You might also remember (or perhaps it is just sad Math geeks like myself that remember this stuff) that the sum of any set of consecutive numbers (starting from 1) is defined the by formula:
(N*(N + 1))/2, where N is the largest of all consecutive numbers in the set. With this knowledge we can sanity check (for our own understanding) whether it does what you should expect it to do or if it was just coincidence above:
def sum(n)
n*(n+1)/2
end
(1..9).inject(0) { |cumulative_sum, item| cumulative_sum + item } #=> 45
sum(9) #=> 45
(1..100).inject(0) { |cumulative_sum, item| cumulative_sum + item } #=> 5050
sum(100) #=> 100
(1..7890).inject(0) { |cumulative_sum, item| cumulative_sum + item } #=> 31129995
sum(7890) #=> 31129995
See told you it wasn't just coincidence - or what everything above a coincidence? Hmmmm..let's not go there right now!:).
I'll bet you could very easily figure out the more general formula for any sum of consecutive positive integers not necessarily starting at 1 (yes, that is one). At least that is what my Mathematics teacher would ask us to do for homework (really not very much homework to be honest - I had a nice teacher)! I'll not make you prove it by induction today though;) Maybe tomorrow...
Now you can do more interesting things instead of just summing consecutive positive integers. Don't just move on to geometric progressions either - the world is your oyster...like finding numerical solutions using an iterative method of your choice using this streamlined apporach!
0 comments:
Post a Comment