Posts Tagged ‘inject’

Ruby Enumerable Magic: Aggregates

December 10, 2010

  1. The Basics
  2. Unary Ampersand Operator
  3. Booleans
  4. Filters
  5. New Collections
  6. Aggregates
 

This final article in my series about the Enumerable module details the methods that don’t quite fit elsewhere, but deal with the collection as a whole. As such, they each return just one object, not an array.

inject

If you haven’t used this method before, it’s loads of fun. It’s a cumulative method that uses each item in the collection to form a “final answer”. The classic example is finding the sum of the numbers in an array:

irb(main):001:0> [1, 2, 3].inject{|sum, num| sum += num}
=> 6

Another use might be finding the initials in a name:

irb(main):008:0> ['Jaime', 'Lee', 'Bellmyer'].inject(''){|initials, name| initials += name[0,1]}
=> "JLB"

In this example, I had to pass the starting string (”, or blank) to inject. Otherwise, it takes the first element as a whole, and starts adding onto it. I don’t like this behavior, and I suspect it works this way because inject assumes you’re trying to sum elements in some way. You also need to pass an initial value to inject when you want the result to be a different class than the inputs:

irb(main):009:0> [1, 2, 3].inject(0.0){|sum, i| sum += i.to_f}
=> 6.0

min and max

These methods behave largely like you’d expect. The items in the collection have to have the <=> method defined, just like the sorting methods, since finding the min and max requires sorting. So strings and numbers behave like you’d expect:

irb(main):010:0> ['joshua', 'gabriel', 'jacob'].min
=> "gabriel"
irb(main):011:0> ['joshua', 'gabriel', 'jacob'].max
=> "joshua"
irb(main):012:0> [1,2,3].min
=> 1
irb(main):013:0> [1,2,3].max
=> 3

And you can also pass your own custom sorting block, like you can with the sort method:

irb(main):014:0> ['joshua', 'gabriel', 'jacob'].min{|a,b| a.reverse <=> b.reverse}
=> "joshua"
irb(main):015:0> ['joshua', 'gabriel', 'jacob'].max{|a,b| a.reverse <=> b.reverse}
=> "gabriel"
irb(main):016:0> [1,2,3].min{|a,b| a*(-1) <=> b*(-1)}
=> 3
irb(main):017:0> [1,2,3].max{|a,b| a*(-1) <=> b*(-1)}
=> 1

In conclusion

What a long journey it has been. I’d like to thank myself for completing my longest series of articles, in the most timely manner yet. And I’d like to thank you if you suffered through all of it for the sake of knowledge. Please feel free to ask any questions you might have, and I’ll do my best to answer them promptly.

And thus concludes our two-week look at the Enumerable module.


Follow

Get every new post delivered to your Inbox.