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

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More