Array

Next, we have a very important class: Array. Most of what we do as developers is manage lists of things. Lists of photos, likes, followers, reviews, listings, messages, rides, events, concerts, projects, etc etc etc.

The first data type we’re going to learn to help us manage lists of things is Array. This class, unlike the ones we’ve seen until now, is really just a container for other objects, and can hold however many objects we want.

Creating arrays

As always, we have the formal way of creating a new object in Ruby: use the .new method on the parent class:

cities = Array.new

Try it out and see what you get if you p cities:

Click here for a REPL to try it.

push

As you can see, Ruby represents an Array with square brackets, []. The brand new array is empty; let’s add some elements to it with the .push method. Try this:

cities = Array.new

cities.push("Chicago")
cities.push("NYC")
p cities

cities.push("LA")
# Add some of your own, if you like
p cities

Now we’re talking! We’ve stored multiple strings within a single array using the .push method1. Ruby separates the elements in an array with commas.

Array literals

Much like with Strings, there’s a shortcut to creating Arrays. Rather than starting with Array.new and building it up from scratch one .push at a time, we can type an array “literal” directly into the code:

cities = ["Chicago", "NYC", "LA"]

This is the technique that we’ll be using most often.

Methods

Now let’s familiarize ourselves with some of Arrays methods.

at

After adding elements to the list, the next most important thing we need to be able to do is retrieve an element back out from the list. Our first tool for doing that is .at.

The .at method takes an Integer argument, which is interpreted as the position, or index, in the Array of the element that you want to retrieve. Give it a try:

cities = ["Chicago", "NYC", "LA", "SF", "NOLA"]

p cities
p cities.at(2)

Click here for a REPL to try it.

Whoa! Did you expect cities.at(2) to return "LA"? I sure didn’t, the first time I tried it; I was expecting "NYC".

It turns out that pretty much every programming language indexes the elements in an array starting at zero, not at one. So the first element is retrieved with cities.at(0), the second element with cities.at(1), etc. You’ll get used to it after a while.

A couple of other things for you to experiment with:

  • What happens when you use an index greater than the length of the array?

    This is our first contact with nil, an object that represents the absence of anything. When you use an index “outside” the array, you might have expected to see an error message; but instead, Ruby returns nil.

  • What happens when you use a negative index?

at shorthand, []

There’s a shorthand for .at() which is very common, so you should be familiar with it. It’s the .[] method, so we could write:

cities = ["Chicago", "NYC", "LA", "SF", "NOLA"]

p cities.[](2) # => "LA"

You guessed it — there’s some syntactic sugar coming up. When a class has a method named .[], Ruby allows the dot to be dropped, but the method name has to then move immediately next to the object it’s being called on (no space), and the argument moves inside the method name! Altogether, this allows us to write:

cities = ["Chicago", "NYC", "LA", "SF", "NOLA"]

p cities[2] # => "LA"

Which is sort of nice. I prefer .at because I think it reads better, but feel free to use the square brackets if you like that style better.

array = [8, 3, 1, 19, 23, 3]

p array[2]

Click here for a REPL to try it.

first, last

Since retrieving the elements at positions 0 (the first one) and -1 (the last one) is so common, there are handy shortcut methods for those: .first and .last. Give them a try.

index

The .index method is sort of the inverse of .at: given an object, .index searches within the array and returns the index where it resides. Give it a try:

cities = ["Chicago", "NYC", "LA", "SF", "NOLA"]

p cities.index("SF")

Click here for a REPL to try it.

Some further things for you to experiment with:

  • What will .index return if the element is present in the array more than once?
  • What will .index return if the element is not present in the array at all?

String#split

Before we proceed with more Array methods, I want to go back for a minute and talk about the .split method from the String class. This method, when called on a String, will return an Array of substrings:

"alice bob carol".split # => ["alice", "bob", "carol"]

If you provide no argument, the string is split upon whitespace, which is handy for e.g. turning a sentence into a list of words:

If you do provide an argument to .split, then the string will be chopped up wherever that argument occurs instead of whitespace — for example, use "4,8,15,16,23,42".split(",") to split on commas.

You can also split with the empty string, "", as an argument in order to turn a string into an Array of its individual characters:

a = "Hello!".split("") # => ["H", "e", "l", "l", "o", "!"]
a.at(0) # => "H"
a.at(-1) # => "!"

This is particularly handy for us because it allows us to get a String of input from users with gets and then transform it into an Array for processing:

p "Enter a series of numbers, separated by spaces:"

user_string = gets.chomp

user_numbers = user_string.split

length = user_numbers.count

p user_string
p user_numbers
p "You entered " + length.to_s + " numbers."

Click here for a REPL to try it.

We’ll be using this technique for the remainder of our test REPLs, to make things more interesting.

count

.count counts how many elements are in the list, if called with no arguments. If an argument is provided, it counts how many times that argument occurs in the list.

a = [8, 3, 1, 19, 23, 3]

p a.count

p a.count(3)

Click here for a REPL to try it.

include?

A thin convenience layer on top of .count, .include? will quickly tell you whether a value is present within an Array:

a = [ "a", "b", "c" ]
a.include?("b")   # => true
a.include?("z")   # => false

You can also negate include? with a ! (prounounced “bang”), to find out whether a list excludes a particular element:

a = [ "a", "b", "c" ]
!a.include?("z")   # => true
!a.include?("b")   # => false

Once we get to Ruby on Rails, a method called exclude? is added that does the same thing. If you want to use the exclude? method outside of Rails, then you must bring the activesupport library into your Ruby program.

require "active_support"

reverse

array = [8, 3, 1, 19, 23, 3]

p array.reverse # => [3, 23, 19, 1, 3, 8]

Click here for a REPL to try it.

sort

array = [12, 4, 5, 13, 56, 32]

p array.sort # => [4, 5, 12, 13, 32, 56]

Click here for a REPL to try it.

shuffle

array = [1, 2, 3, 4, 5]

p array.shuffle # Returns a copy of array in random order

Click here for a REPL to try it.

sample

array = [8, 3, 1, 19, 23, 3]

p array.sample # => Returns a single random element from the array

Click here for a REPL to try it.

min

a = [8, 3, 1, 19, 23, 3]

p a.min # => 1

Click here for a REPL to try it.

max

a = [8, 3, 1, 19, 23, 3]

p a.max # => 23

Click here for a REPL to try it.

sum

a = [8, 3, 1, 19, 23, 3]

p a.sum # => 57

Click here for a REPL to try it.

join

You can think of Array’s .join method as the inverse of String’s .split method:


"hello!".split("")
# => ["h", "e", "l", "l", "o", "!"]

["h", "e", "l", "l", "o", "!"].join
# => "hello!"

That is, the .split method is called on a String and returns an Array of substrings; while the .join method is called on an Array (where each element must be a String) and returns a single String.

  1. You might come across a shorthand for .push, the << method, known as the “shovel” operator. This allows you to write something like:

    cities.<<("Chicago")
    

    Or with the syntactic sugar that we’re very accustomed to by now:

    cities << "Chicago"
    

    I personally prefer .push — I think it’s more readable — but feel free to use the shovel if you like it better.