DEV Community

Alexa Anderson
Alexa Anderson

Posted on

Ruby's Enumerable Module

One of the most useful built-in modules is ruby's Enumerable. While it may invoke an eye-roll during an algorithmic tech screen, on the job, these functions are found in most, if not all, codeblocks involving Arrays or Hashes.

Here's a definitive view of Enumerable with examples.

peace = 'this,thing,the,other,thing'
items = peace.split(',')

# Module Enumerable

## Method: Each

#### The enumerable module requires the including or extending class define a `.each` method.
#### This method is expected to yield successive elements to the calling block.
#### This method is used as an implementation detail of most Enumerable methods.

### Call a block with each successive element
items.each { |i| print i } # prints "this" then prints "thing" then prints "the" then prints "other" then prints "thing"
Enter fullscreen mode Exit fullscreen mode

This interactive Ruby Environment is available for hands-on practice with Enumerable:


## Querying: Return information

### Check for inclusion
items.member? 'this' # true
items.member? 'grape' # false
items.include? 'this' # true
items.include? 'grape' # false

### Check for omnipresence
items.all? { |i| i.class === String } # true
items.all? { |i| i === 'this' } # false

### Check for at least one
items.any? { |i| i.class === String } # true
items.any? { |i| i === 'grape' } # false

### Check for anti-presence
items.none? { |i| i.class === Integer } # true
items.none? { |i| i.class === String } # false

### Check for exactly one
items.one? { |i| i === 'this' } # true
items.one? { |i| i === 'thing' } # false

### Count the number of member elements
items.count # 5
items.count { |i| i === 'thing' } # 2

### Get hash of occurance counts by item
items.tally # { "this"=>1, "thing"=>2, "the"=>1, "other"=>1 }

## Fetching: Return element(s) without modifying

### Return all elements
items.to_a # ["this", "thing", "the", "other", "thing"]
items.tally.to_a # [["this", 1], ["thing", 2], ["the", 1], ["other", 1]]
items.entries # ["this", "thing", "the", "other", "thing"]
items.tally.entries # [["this", 1], ["thing", 2], ["the", 1], ["other", 1]]

### Return first element
items.first # "this"

### Return the last element
items.last # "thing"

### Return some number of leading elements
items.take(2) # ["this", "thing"]

### Return some number of trailing elements
items.drop(2) # ["other", "thing"]

### Return leading elements as specified
items.take_while { |i| [4,5].include? i.length } # ["this", "thing"] 

### Return trailing elements as specified
items.drop_while { |i| [4,5].include? i.length } # ["the", "other", "thing"]

### Return elements of the smallest value using <=>
items.min # "other"
items.min(2) # ["other", "the"]
items.min { |a,b| a.size <=> b.size } # "the"
items.min(2) { |a,b| a.size <=> b.size } # ["the", "this"]

### Return elements of the largest value using <=>
items.max # "this"
items.max(2) # ["this", "thing"]
items.max { |a,b| a.size <=> b.size } # "thing"
items.max(2) { |a,b| a.size <=> b.size } # ["other", "thing"]

### Return smallest and largest elements
items.minmax # ["other", "this"]

### Return smallest element as specified
items.min_by { |i| i.length } # "the"

### Return largest element as specified
items.max_by { |i| i.length } # "thing"

### Return smallest and largest element as specified
items.minmax_by { |i| i.length } # ["the", "thing"]

### Return hash of elements grouped as specified
items.group_by { |i| i[0] } # { "t"=>["this", "thing", "the", "thing"], "o"=>["other"] }

### Return two arrays of elements partitioned as specified
items.partition { |i| i[0] === 't' } # [["this", "thing", "the", "thing"], ["other"]]

### Return enumerator of entries partitioned by given condition
items.slice_before { |i| i === 'thing' } # => #<Enumerator: ...>
items.slice_before { |i| i === 'thing' }.to_a # [["this"], ["thing", "the", "other"], ["thing"]]
items.slice_after { |i| i === 'thing' } # => #<Enumerator: ...>
items.slice_after { |i| i === 'thing' }.to_a # [["this", "thing"], ["the", "other", "thing"]]

### Return enumerator of entries grouped as specified
items.chunk { |i| i[0] } # => #<Enumerator: ...>
items.chunk { |i| i[0] }.to_a # [["t", ["this", "thing", "the"]], ["o", ["other"]], ["t", ["thing"]]]

### Return enumerator of entries sequentially grouped as specified
items.chunk_while { |a,b| a[0] == b[0] } # => #<Enumerator: ...>
items.chunk_while { |a,b| a[0] == b[0] }.to_a # [["this", "thing", "the"], ["other"], ["thing"]]

## Search and Filter

### Return first element as specified
items.find { |i| i == 'thing' } # "thing"
items.find { |i| i == 'grape' } # nil
items.detect { |i| i == 'thing' } # "thing"
items.detect { |i| i == 'grape' } # nil

### Return multiple elements as specified
items.find_all { |i| i == 'thing' } # ["thing","thing"]
items.find_all { |i| i == 'grape' } # []

### Return the index of the first element matching the condition
items.find_index { |i| i == 'thing' } # 1
items.find_index { |i| i == 'grape' } # nil

### Return array of elements not rejected by the condition
items.reject { |i| i[0] == 't' } # ["other"]

### Return array of elements which are not duplicated
items.uniq # ["this", "thing", "the", "other"]

### Return array of elements which match the specified object or pattern
items.grep(String) # ["this", "thing", "the", "other", "thing"]
items.grep(/thing/) # ["thing", "thing"]

### Return array of element which do not match the object or pattern
items.grep_v(String) # []
items.grep_v(/thing/) # ["this", "the", "other"]

## Sort

### Return elements sorted by <=> or as specified
items.sort # ["other", "the", "thing", "thing", "this"]
items.sort { |a,b| a[a.size-1] <=> b[b.size-1] } # ["the", "thing", "thing", "other", "this"]

## Return elements sorted as specified
items.sort_by { |i| i[i.size - 1] } # ["the", "thing", "thing", "other", "this"]

## Iterate

### Call a block with each successive element
items.each_entry { |i| print i } # prints "this" then "thing" et cetera

### Call a block with each successive element and its index
items.each_with_index { |i, idx| print "#{i} is at index #{idx}"} # prints "this is at index 0" et cetera

### Call a block with each successive element and an object
items.each_with_object([]) { |i, obj| obj << i[0..1] } # ["th", "th", "th", "ot", "th"]

### Make an enumerable of entries partitioned by size and call a block with each partition
items.each_slice(2) { |s| print s[0] } # prints "this" then prints "the" et cetera

### Make an enumerable of entries of specified size starting at each element and call a block on each partition
items.each_cons(2) # => #<Enumerable: ...>
items.each_cons(2).to_a # [["this", "thing"], ["thing", "the"], ["the", "other"], ["other", "thing"]]
items.each_cons(2) { |p| print p[0] } # prints "this" then prints "thing" et cetera

### Call a block with each successive element in reverse order
items.reverse_each { |i| print i } # prints "thing" then print "other" et cetera

## Other Methods

### Return a array of values by processing each entry as specified
items.map { |i| i.upcase } # ["THIS", "THING", "THE", "OTHER", "THING"]
items.collect { |i| i.upcase } # ["THIS", "THING", "THE", "OTHER", "THING"]

### Return an array of values which evaluate to truthy after processing each entry as specified
items.filter_map { |i| i[3] } # ["s", "n", "e", "n"]

### Return a single-dimension array as specified
items.flat_map { |i| [i, i.upcase] } # ["this", "THIS", "thing", "THING", "the", "THE", "other", "OTHER", "thing", "THING"]
items.tally.flat_map { |key, value| [key, value] } # ["this", 1, "thing", 2, "the", 1, "other", 1]

### Return the object formed by combining elements as specified
items.reduce('') { |obj, i| obj + i } # "thisthingtheotherthing"
items.inject('') { |obj, i| obj + i } # "thisthingtheotherthing"

### Return a summation object of elements using "+"
items.sum('') # "thisthingtheotherthing"
items.sum('') { |i| i[0] == 't' ? i : '' } # "thisthingthething"

### Return an array with each index being a combination of elements at the zipped arrays' indices
items.zip # [["this"], ["thing"], ["the"], ["other"], ["thing"]]
items.zip([]) # [["this", nil], ["thing", nil], ["the", nil], ["other", nil], ["thing", nil]]
items.zip(items.tally) # [["this", ["this", 1]], ["thing", ["thing", 2]], ["the", ["the", 1]], ["other", ["other", 1]], ["thing", nil]]

### Call a given block for each entry a specified number of times
items.cycle(2) { |i| print i[0] } # prints the first letter of each element, "t" then "t" then "t" then "o" then "t", two times
Enter fullscreen mode Exit fullscreen mode

Top comments (0)