DEV Community

Cover image for Understanding Ruby - Enumerable - Predicate Conditions
Brandon Weaver
Brandon Weaver

Posted on • Edited on

Understanding Ruby - Enumerable - Predicate Conditions

Introduction

Enumerable. Debatably one of, if not the, most powerful features in Ruby. As a majority of your time in programming is dealing with collections of items it's no surprise how frequently you'll see it used.

Difficulty

Foundational

Some knowledge required of functions in Ruby. This post focuses on foundational and fundamental knowledge for Ruby programmers.

Prerequisite Reading:

Enumerable

Enumerable is an interface module that contains several methods for working with collections. Many Ruby classes implement the Enumerable interface that look like collections. Chances are if it has an each method it supports Enumerable, and because of that it's quite ubiquitous in Ruby.

Note: This idea was partially inspired by Lamar Burdette's recent work on Ruby documentation, but takes its own direction.

Predicate Conditions

Predicate conditions are Enumerable methods which allow us to ask a question of a collection. Are all of the elements matching a condition? Perhaps just one of them? Maybe any? ...or does it even include it at all?

#all?

all? is a predicate method, meaning it's boolean or truthy in nature. For all? it checks all items in a collection meet a certain condition:

[1, 2, 3].all? { |v| v.even? }
# => false
Enter fullscreen mode Exit fullscreen mode

We can also use shorthand here:

[1, 2, 3].all?(&:even?)
Enter fullscreen mode Exit fullscreen mode

...and interestingly it also accepts a pattern, or rather something that responds to ===:

[1, 2, 3].all?(Numeric)
# => true
Enter fullscreen mode Exit fullscreen mode

all? will also stop searching if it finds any element which does not match the condition.

An interesting behavior is that it will return true on empty collections:

[].all?
# => true
Enter fullscreen mode Exit fullscreen mode

all? is great when you want to check if all of a collections items meet a condition, or perhaps many.

#any?

any? is very similar to all? except in that it checks if any of the items in a collection match the condition:

[1, 'a', :b].any?(Numeric)
Enter fullscreen mode Exit fullscreen mode

Interestingly as soon as it finds a value that matches it will stop searching. After all, why bother? It found what it wanted, and it's way more efficient to say return true rather than go through the rest.

With an empty collection any? will return false as there are no elements in it:

[].any?
# => false
Enter fullscreen mode Exit fullscreen mode

any? is great for checking if anything in a collection matches a condition.

#none?

none? can be thought of as the opposite of all?, or maybe even as not any?. It checks that none of the elements in a collection match a certain condition:

[1, 'a', :b].none?(Float)
# => true
Enter fullscreen mode Exit fullscreen mode

none? will return true on an empty collection:

[].none?
# => true
Enter fullscreen mode Exit fullscreen mode

Be careful, as this behavior is very similar to all? which also returns true.

none? can be great for ensuring that nothing in a collection matches a negative set of rules, like simple validations.

#one?

one? is very much like any? except in it will search the entire collection to make sure there's one and only one element that matches the condition:

[1, :a, 2].one?(Symbol)
# => true

[1, :a, 2].one?(Numeric)
# => false
Enter fullscreen mode Exit fullscreen mode

It has some interesting behavior when used without an argument on empty or single element collections:

[].one?
# => false

[1].one?
# => true
Enter fullscreen mode Exit fullscreen mode

one? is great when you want to ensure one and only one element of a collection matches a condition. I have not quite had a chance to use this myself, but can see how it would be handy.

#include? / #member?

include? checks if a collection includes a value:

[1, 2, 3].include?(2)
# => true
Enter fullscreen mode Exit fullscreen mode

It has an alias in member?.

include? will compare all elements via == to see if any match the one we're looking for.

Wrapping Up

The next few articles will be getting into the various parts of Enumerable, grouped by functionality:

  1. Transforming
  2. Predicate Conditions
  3. Searching and Filtering
  4. Sorting and Comparing
  5. Counting
  6. Grouping
  7. Combining
  8. Iterating and Taking
  9. Coercion

While lazy is part of Enumerable that deserves a post all its own, and we'll be getting to that one soon too.

Want to keep up to date on what I'm writing and working on? Take a look at my new newsletter: The Lapidary Lemur

Top comments (2)

Collapse
 
thorstenhirsch profile image
Thorsten Hirsch

Hi Brandon, here's a little mistake:

[1, :a, 2].one?(Numeric)
# => true
Enter fullscreen mode Exit fullscreen mode

It returns false, because 2 values are Numeric.

Collapse
 
baweaver profile image
Brandon Weaver

Whoops, forgot to switch that comment to false. Nice catch!