Back to Home

Ruby Enumerable

If you are still using a 'loop', STOP.

There are better and easier way to do it. Ruby provides various enumerables that can go through all element and yields successive members of the collection.

animal = {} %w(cat dog rabbit).each_with_index { |item, index| animal[item] = index } animal => {"cat"=>0, "dog"=>1, "rabbit"=>2}
(1..10).find_all { |i| i % 3 == 0 } => [3, 6, 9] **returns array
(1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } => 34
(1..100).grep 38..44 **returns array=> [38, 39, 40, 41, 42, 43, 44]
(1..6).group_by { |i| i%3 } **returns hash=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
(1..10).each_slice(3) { |a| p a } **returns array of slice number [1, 2, 3] [4, 5, 6] [7, 8, 9] [10]

Reduce takes in an array and reduce to a single value.It does this by iterating through a list, keeping and transforming a running total along the way. This running total can be a single value like 0, 3.7, “abcdefg”, a collection ([], {}), or anything else, really. Each iteration starts with the return value of the previous iteration and does something with it.

(5..10).reduce(:+) #=> 45 (5..10).reduce(0){|sum, num| sum+= (num * num + 1)} #=> 361 (5..10).inject(1){|product, n| product * n } #=> 151200 # inject and reduce are interchangable.

Let’s look at a slightly more complicated case. reduce can be used to implement just about any other collection function, from map to sort to select. Here is a way to emulate select using reduce.

(1..10).reduce([]) do |result, value| result << value if value > 5 result end => [6, 7, 8, 9, 10] (1..10).reduce([]) do |result, value| result << value * value result end => [1, 4, 9, 25, 36, 49, 64, 81, 100] longest = %w{ cat sheep bear }.reduce do |memo, word| memo.length > word.length ? memo : word end puts longest => "sheep"

The keyword min, mas and minmax use exactly same method except the return values.

a = %w(albatross dog horse) a.max { |a, b| a.length <=> b.length } => "albatross" a.max_by { |x| x.length } => "albatross" **If any number is passed, it will return array a.max_by(2) {|x| x.length } => ["albatross", "horse"] a.minmax { |a, b| a.length <=> b.length } => ["dog", "albatross"]

The keyword partition returns two arrays, the first containing the elements of enum for which the block evaluates to true, the second containing the rest.

(1..6).partition { |v| v.even? } => [[2, 4, 6], [1, 3, 5]]
%w{apple pear fig}.sort_by { |word| word.length} => ["fig", "pear", "apple"]

Awesome methods that you don't need to calculate the result

require 'prime' Prime.entries 10 => [2, 3, 5, 7]

More importantly, here is a useful sites.

  • Ruby Document

  • Guide to Ruby Collection III

  • Ruby Explained