Looping with Arrays
Learning Goals
- Use arrays to loop a specific number of times
- Access each element in an array programmatically
Introduction
Arrays are often used to hold collections of related values. However, the power of arrays is made much clearer when we can work with all the data they contain.
So far, we've learned how to add and remove values from arrays, as well as access and change specific values. It is time to start putting arrays to work. So far, we've been working on arrays that we can see ahead of time.
pets = ["Dog", "Cat", "Fish", "Bird"]
Above, we can see what elements are present and what order they are in. However, as we build more complex projects, we will start to run into situations where we have to handle an array that we don't know the contents of or how many elements there actually are inside!
We need to take a programmatic approach to this. We previously brought up the concept of abstracting code - that is, writing code that moves away from concrete details in favor of a reusable, generalized process.
In this lesson, we're going to discuss one of the most common ways to handle arrays abstractly - we will be using loops to access their elements.
Hard-Coding Array Output
Let's consider the pets
example a little further.
pets = ["Dog", "Cat", "Fish", "Bird"]
Say we wanted to output each element in the pets
array. We could write:
puts pets[0] #=> Dog
puts pets[1] #=> Cat
puts pets[2] #=> Fish
puts pets[3] #=> Bird
This works, but it is what programmers refer to as hard-coded. Hard-code is
code that is fixed in place. The above statements all rely on the assumption
that the pets
array is going to be four elements long. If we modified the
pets
array, say we want to add an additional pet, the hamster. We go ahead and
add "Hamster" to our array:
pets << "Hamster"
But now, if we want to output hamster, we also have to add an additional puts
statement:
puts pets[4] #=> Hamster
Without this addition, Hamster
would never be output to the terminal. Every
change we make to the pets
array would require an additional modification to
our code. In a complex program, this can quickly become a major headache.
By using a loop, however, we can abstract away the need for additional modifications.
Abstracting Array Output
Given our pets
array, it would be great to simply say "for every element in
this array, output the element to the terminal." This way, even if the array
changed, we'd always output each and every element.
With loops, we can do this! A very basic example would be a while loop with a counter:
counter = 0
pets = ["Dog", "Cat", "Fish", "Bird", "Hamster"]
while pets[counter] do
puts pets[counter]
counter += 1
end
The above code outputs:
Dog
Cat
Fish
Bird
Hamster
So what is happening here? Remember that Ruby considers nil
to be a falsy
value. If we step through this loop, we can see why this works.
-
When the Ruby interpreter first gets to the
while
loop,counter
is equal to0
, sopets[0]
returns"Dog"
. Because"Dog"
is a truthy value, the loop executes andpets[0]
is output to the terminal. Then,counter
is incremented by1
. -
When the first loop completes, Ruby checks the condition for the
while
loop again. This time,counter
is equal to1
.pets[1]
returns"Cat"
, causing the loop to execute again, outputtingpets[1]
and incrementingcounter
. -
On the third, fourth and fifth loops, the same things occurs.
pets[2]
returns"Fish"
,pets[3]
returns"Bird"
, andpets[4]
returns"Hamster"
. All three are then output to the terminal. -
On the last loop,
counter
is incremented to5
. However, there is no sixth element in the array, sopets[5]
returnsnil
. This stops thewhile
loop.
With this set up, no matter how long or short the pets
array is, the loop will
output each element! We've built a pet printer that works no matter how many
pets are in our pets
array!
We could go further than this, though, by placing our while
loop in a method.
Instead of just a pet printer, we can turn this code into an all purpose
element printer:
def output_array_elements(array)
counter = 0
while array[counter] do
puts array[counter]
counter += 1
end
end
Now, we could still use this for pets and get the same results:
pets = ["Dog", "Cat", "Fish", "Bird", "Hamster"]
output_array_elements(pets)
But we could also use output_array_elements
with all kinds of arrays!
output_array_elements(["hello", "how are you?", "goodbye!"])
The above code would produce:
hello
how are you?
goodbye!
Looping Using the Array Length Method
An common alternative to the previous example is to utilize the methods built in
to the Ruby Array
class. Specifically, in these situations, we want to loop
as many times are there are elements. To find out how many elements are in an
array, we can use the length
method:
array = ["Spring", "Summer", "Fall", "Winter"]
array.length
#=> 4
Note: Ruby arrays also have methods called
size
andcount
that all perform the same function - return the number of elements in the array.
Now that we can get the length, we would want to structure our loop so that
we compare the value of counter
with this length value. Updating the method
from the previous section, this might look something like:
def output_array_elements(array)
counter = 0
while counter < array.length do
puts array[counter]
counter += 1
end
end
As long as counter
is less than the return value of array.length
, the loop
will execute.
Iteration
Using a loop to access each element in an array is very common in programming and is generally referred to as iteration. We iterate over each element, in these examples, printing out the values. In other examples, we might want to iterate over an array and update each element's value. If the values were numbers, we could do things like sum all the values together using while loops and basic iteration.
Conclusion
Loops are a powerful tool for working with arrays. With just a small amount of code, we perform operations on every element in an array, regardless of how many elements there are!