Books / Ruby for Beginners / Chapter 22

Array Methods in Ruby

empty? method

Question mark at the end of a method indicates that method returns Boolean type (true or false). Use “empty?” method to check whether array has elements or empty. If array is empty, method returns true.

$ pry
> [].empty?
 => true

Keep in mind that “nil” object doesn’t implement “empty?” method. So if some method returns nil or array (which can be empty), you have to perform double check:

arr = some_method

if !arr.nil? && !arr.empty?
  puts arr.inspect

Also, there is one important detail you don’t want to miss. Every Ruby programmer sooner or later will use Rails framework. And Rails has some additional helpers for certain types to simplify your life as developer. For example, Rails will let you avoid double checks like in example above. Instead you can just use “blank?”:

if !arr.blank?
  puts arr.inspect

Or the opposite “present?”:

if arr.present?
  puts arr.inspect

Will you agree that the first line looks better than the line below?

if !arr.nil? && !arr.empty?

In other words, use “empty?” when there is no Rails framework and you’re working on Ruby-only project. But always prefer “present?” and “blank?” when you’re working with Rails. These two methods are implemented for many types, and it would be really helpful if you can bookmark this page, so you can always refer to the following table:

Rails blank? and present? methods for different types

As you can see from the table above, “blank?” and “present?” are opposite (two last columns). And the second column says that only “nil” and “false” evaluate to “false”. In other words, all if-statements below are evaluated to “true” and will be executed:

if true
  # will be executed

if ''
  # will be executed

if ' '
  # will be executed

if []
  # will be executed

# ...

And so on…

From the table above we can see that method “empty?” is implemented for String, Array, and Hash.

Methods length, size, count

Methods “length” and “size” are identical and implemented for Array, String, Hash types:

[11, 22, 33].size # => 3
[11, 22, 33].length # => 3

str = 'something'
str.size # => 9
str.length # => 9

hh = { a: 1, b: 2 }
hh.size # => 2
hh.length # => 2

Method “count” works the similar way, but:

  • It’s not implemented for String
  • It can accept block

We can take advantage of block passed to “count” method to get some really handy calculations. Here is, for example, how you count a number of zeroes in array:

$ pry
> [0, 0, 1, 1, 0, 0, 1, 0].count { |x| x == 0 }

count” method can be used with a pointer to a function (we haven’t covered this topic yet, but example below gives a basic idea of how it works). The following line does the same thing as the line above:

[0, 0, 1, 1, 0, 0, 1, 0].count(&:zero?)

It’s important to know that “count” with a block goes over entire collection, and if you use Rails framework with “count” you wanna make sure that your query is efficient.

Exercise Calculate the number of even elements in the following array: [11, 22, 33, 44, 55]

include? method

include?” method performs existence check over array and returns Boolean value. For example:

$ pry
> [1, 2, 3, 5, 8].include?(3)

Interesting detail is that some folks from Ruby community always wanted to rename this method to “includes?”, but it didn’t happen. So you have to remember that it comes without “s”. In JavaScript ES6 existence check uses the “correct” spelling:

$ node
> [1, 2, 3, 5, 8].includes(3);

Adding Elements to Arrays

Adding and removing elements is implemented with methods we already know: “push” and “pop”. These methods perform operations with the tail of an array: add element to the end, remove from the end. It looks like a stack of plates, where you push and pop from the top.

However, there are “unshift” and “shift” methods that do the same, but with the head of an array:

  • unshift” is similar to “push
  • shift” is similar to “pop

The metaphor here could be that “shift” shifts elements and returns one that didn’t fit.

Selecting Elements by Criteria

Imagine that we have a list of employees with their ages. We need to pick all the males who are going to retire next year. For simplicity let’s assume that employee is represented by an object. We are not familiar with Hash data structure yet, so let’s use Array. First element of this array is going to be age, and the second is gender. Meet the male with the age of 30:

[30, 1]

Female with the age of 25:

[25, 0]

And we have a list of such objects (array of objects, or two-dimensional array):

[ [30, 1], [25, 0], [64, 1], [64, 0], [33, 1] ] 

Select all males with the age of 64:

$ pry
> arr = [ [30, 1], [25, 0], [64, 1], [64, 0], [33, 1] ]
> { |element| element[0] == 64 && element[1] == 1 }
(...1 element was selected...)

Select all males:

$ pry
> arr = [ [30, 1], [25, 0], [64, 1], [64, 0], [33, 1] ]
> { |element| element[1] == 1 }
(...3 elements were selected...)

Practice a bit in your REPL and try to select all females.

Rejecting Elements by Criteria

Method “reject” works the opposite way, comparing to “select”. It rejects elements by criteria.

Reject all males of the age 30 or above:

$ pry
> arr = [ [30, 1], [25, 0], [64, 1], [64, 0], [33, 1] ]
> arr.reject { |element| element[0] >= 30 }

Take Method

Method “take” takes certain number of elements from the beginning of a collection:

$ pry
> [11, 22, 33, 44, 55].take(2)
 => [11, 22]

Is There Any Match? (any?)

Imagine we have array that represents result of a lottery. Each cell is either true or false. We need to know if there are any wins (“true” element). Method “any?” has question mark at the end, so it always returns Boolean: true or false.

any?” must be executed with a block, and block should have comparison expression. This comparison expression will be executed sequentially until condition is met (equals true):

$ pry
> [false, false, false, true, false].any? { |element| element == true }

Code above shows that there is actually a win among these five tickets. Method “any?” just indicates that there is a win in this array, but it can’t tell which ticket is winning.

In other words, method doesn’t return any index. If you want to find index of a winning ticket, Ruby’s principle of a least surprise suggests that there should be “find_index” method for that. And it actually exists!

$ pry
> [false, false, false, true, false].find_index { |element| element == true }

All Elements Should Meet Criteria

Imagine that we have an array with ages of our users. We need to ensure that all of them are 18 or above. How would you do that? By using “all?” method:

$ pry
> [20, 34, 65, 23, 18, 44, 32].all? { |element| element >= 18 }

Summary of Array Methods in Ruby

We’ve discovered the following methods for Array class:

  • push, pop - add and remove element from array
  • arr[i] - access by index
  • empty? - check if array is empty
  • length, size, count - similar methods to get the size of array or get the count of elements by criteria
  • include? - check if array includes certain element
  • select, reject - select or reject elements by criteria
  • take - take some elements from the beginning
  • any?, all? - check if some or all elements meet certain criteria

You don’t need to remember all of them now, but it’s worth adding a bookmark here. Eventually you will remember and recognize these methods. Moreover, all of these methods were re-implemented in Rails web framework to deal with collections. Here are some examples how you can use them:

  • Select all registered users
  • Reject users with unconfirmed email address
  • Select users by certain criteria (age, gender, payment method, etc.)
  • Take first/next 10 users from collection to display them on page 1, page 2, and so on.

Licenses and Attributions

Speak Your Mind