1.7 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.
1.7.1 Creating arrays
As always, we have the formal way of creating a new object in Ruby: use the .new
method on the parent class:
Array.new cities =
Try it out and see what you get if you p cities
:
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:
Array.new
cities =
"Chicago")
cities.push("NYC")
cities.push(
p cities
"LA")
cities.push(# 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
method
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.. Ruby separates the elements in an array with commas.
Array literals
Much like with String
s, there’s a shortcut to creating Array
s. 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:
"Chicago", "NYC", "LA"] cities = [
This is the technique that we’ll be using most often.
1.7.2 Methods
Now let’s familiarize ourselves with some of Array
’s 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:
"Chicago", "NYC", "LA", "SF", "NOLA"]
cities = [
p cities2) p cities.at(
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 returnsnil
.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:
"Chicago", "NYC", "LA", "SF", "NOLA"]
cities = [
2) # => "LA" p cities.[](
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:
"Chicago", "NYC", "LA", "SF", "NOLA"]
cities = [
2] # => "LA" p cities[
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.
8, 3, 1, 19, 23, 3]
array = [
2] p array[
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:
"Chicago", "NYC", "LA", "SF", "NOLA"]
cities = [
"SF") p cities.index(
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 a method for the String
class: .split
. 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:
"Hello!".split("") # => ["H", "e", "l", "l", "o", "!"]
a = 0) # => "H"
a.at(1) # => "!" a.at(-
BENP: need an exercise here, split("") is important in .each project. Also, first time with negative indexing? Maybe insert something about this earlier in section (with exercise)
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:
"Enter a series of numbers, separated by spaces:"
p
user_string = gets.chomp
user_numbers = user_string.split
length = user_numbers.count
p user_string
p user_numbers"You entered " + length.to_s + " numbers." p
We’ll be using this technique frequently to make things more interesting.
Open the GitPod Array
project for this chapter and start with the exercise element_square.rb
:
LTI{Load assignment}(https://github.com/bpurinton-appdev/array-chapter/tree/bp-additions)[MV4dKHMwdAFhfRn752YW3TAY]{KBpPhe42o6wDRi35rWagKY4F}(20)[array_project]
For a GitPod refresher, see here.
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.
8, 3, 1, 19, 23, 3]
a = [
p a.count
3) p a.count(
BENP: add project with count() with an argument, becomes important again in .each
Return to the GitPod Array
project and work through count.rb
include?
A thin convenience layer on top of .count
, .include?
will quickly tell you whether a value is present within an Array
:
"a", "b", "c" ]
a = [ "b") # => true
a.include?("z") # => false a.include?(
exclude?
Similar to .include?
, but the opposite:
"a", "b", "c" ]
a = [ "b") # => false
a.exclude?("z") # => true a.exclude?(
reverse
8, 3, 1, 19, 23, 3]
array = [
# => [3, 23, 19, 1, 3, 8] p array.reverse
Return to the GitPod Array
project and work through reverse.rb
sample
8, 3, 1, 19, 23, 3]
array = [
# => Returns a single random element from the array p array.sample
max
8, 3, 1, 19, 23, 3]
a = [
# => 23 p a.max
Return to the GitPod Array
project and work through min_max_difference.rb
sum
8, 3, 1, 19, 23, 3]
a = [
# => 57 p a.sum
Return to the GitPod Array
project and work through sum_elements.rb
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
.