Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 The power of inject
Index -> Programming, Ruby -> Ruby Tutorials
View previous topic Printable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
wtd




PostPosted: Tue Apr 05, 2005 2:37 am   Post subject: The power of inject

For operations on arrays Ruby offers us a powerful feature from the functional programming realm. What's classically known as "fold" or "reduce" there is the inject method in Ruby (the name is from Smalltalk).

Let's consider the simple ask of summing an array of integers.

The simple imperative solution we've probably all seen is:

code:
arr = [1, 3, 23, 56, 789]
sum = 0

arr.each { |x| sum += x }


This isn't too bad. Ruby makes the loop quite expressive.

But we can do better.

Inject involves taking each element of an array and adding it to the result of doing the same operation on the previous element. Of course, since there is no previous result for he first elemen, we supply an initial value. For addition, let's start with an initial value of zero.

code:
arr = [1, 3, 23, 56, 789]

sum = arr.inject(0) { |a, b| a + b }


Consider also an example for finding the product of an array of numbers.

code:
arr = [1, 3, 23, 56, 789]

product = arr.inject(0) { |a, b| a * b }


Questions? Comments?
Sponsor
Sponsor
Sponsor
sponsor
jamonathin




PostPosted: Tue Apr 05, 2005 7:45 am   Post subject: (No subject)

What exactly does this do/mean Confused
code:
{ |a, b| a * b }
Tony




PostPosted: Tue Apr 05, 2005 9:18 am   Post subject: (No subject)

it's a block where |a,b| represent two values in an array and a*b is the function applied to the said values.
jamonathin




PostPosted: Tue Apr 05, 2005 11:43 am   Post subject: (No subject)

Does the ' a * b ' have to be in the | a,b |, it can't be like
code:
{ |a, b| c * d }
Tony




PostPosted: Tue Apr 05, 2005 12:31 pm   Post subject: (No subject)

well since nether C nor D relate to the block of variables, you might as well pre-calculate the result of the function, such as
Ruby:

{|a,b| 42}

So to make it clear - you're not restricted to array's objects. You can, for example, have a *5
wtd




PostPosted: Tue Apr 05, 2005 12:33 pm   Post subject: (No subject)

tony wrote:
it's a block where |a,b| represent two values in an array and a*b is the function applied to the said values.


Yes, it's a block.

code:
|a, b|


Says "the block accepts two arguments, and we'll call them a and b."

code:
a + b


Is saying the block returns "the sum of a and b."

In this case, though, a and b do not represent two values taken from the array. Rather, a represents the value of the previous operation and b the current element in the array.

For an array like:

code:
[1, 3, 23, 56, 789]


It would look like:

code:
((((0 + 1) + 3) + 23) + 56) + 789
(((1 + 3) + 23) + 56) + 789
((4 + 23) + 56) + 789
(27 + 56) + 789
83 + 789
872
jamonathin




PostPosted: Wed Apr 06, 2005 9:59 am   Post subject: (No subject)

ohhh ok, I get it guys, thanks lots Very Happy
wtd




PostPosted: Wed Apr 06, 2005 1:01 pm   Post subject: (No subject)

tony wrote:
well since nether C nor D relate to the block of variables, you might as well pre-calculate the result of the function, such as
Ruby:

{|a,b| 42}


If you're not using a block's parameter, then don't include it at all.

code:
$ irb
irb(main):001:0> [1,2,3].inject(0) { |a, b| 42 }
=> 42
irb(main):002:0> [1,2,3].inject(0) { 42 }
=> 42
irb(main):003:0>
Sponsor
Sponsor
Sponsor
sponsor
wtd




PostPosted: Fri Nov 11, 2005 5:56 pm   Post subject: (No subject)

What can we do with inject?

We can reverse an Array.

code:
>> foo = [3, 5, 1, 8]
=> [3, 5, 1, 8]
>> foo.inject([]) { |a, b| a.unshift b }
=> [8, 1, 5, 3]


We can find the length of an Array.

code:
>> foo = [3, 5, 1, 8]
=> [3, 5, 1, 8]
>> foo.inject(0) { |a, _| a + 1 }
=> 4


We can get the keys from a Hash.

code:
>> bar = {"hello" => "world", "foo" => "bar"}
=> {"foo"=>"bar", "hello"=>"world"}
>> bar.inject([]) { |a, b| a << b.first }
=> ["foo", "hello"]


We can invert a Hash.

code:
>> bar = {"hello" => "world", "foo" => "bar"}
=> {"foo"=>"bar", "hello"=>"world"}
>> bar.inject({}) { |a, b| a[b.last] = b.first; a }
=> {"world"=>"hello", "bar"=>"foo"}


These are just a few examples.
Display posts from previous:   
   Index -> Programming, Ruby -> Ruby Tutorials
View previous topic Tell A FriendPrintable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 9 Posts ]
Jump to:   


Style:  
Search: