1. Computing

Introduction to Arrays


Introduction to Arrays

All programming languages have some sort of ordered collections. Even down to machine code, you can store values in contiguous regions of memory (like a C array), or in a linked list. There are even entire programming languages largely based on creating and manipulating such ordered arrays (such as LISP). In Ruby, the primary way to represent an ordered collection of objects is the Array class. And, this being Ruby, it has a rich feature set.

Ordered Collections

In the past, you may have learned about Hashes. A Hash is an unordered collection. You put objects in in any order, and it doesn't matter in what order you take them out. To iterate over a Hash is to (in theory) pull the keys out at random and retrieve their values (though, in practice, Hashes may iterate over keys in a predictable manner). In fact, it's quite odd that you may have learned about Hashes before Arrays as many Ruby programmers do. In many languages, the Hash is a rather small corner of the data structure ecosystem. In fact, C++ has many types of Arrays (this includes things like Vectors and Dequeues), but only a few Hash-like classes in its standard template library. However, don't let that fool you into thinking ordered collections take a back seat in Ruby.

An ordered collection is any object holding a set of objects that, when stored in the object, may be retrieved in the same order. The only meta-data identifying any particular object in the collection is its place (or index) in that collection. This index may be important, or the collection may simply be seen as a set of related objects. In Ruby, ordered collections are handled by the Array class.

Creating Arrays

Being so important, there are several Array literal syntaxes that may be used. The most common is the square bracket syntax, inside the brackets a comma separated list of elements to be inside the array. Also common is creating an empty array using an opening and closing square bracket with no list inside. Below are a few simple examples.

arr1 = [ 'test' ]  # A single element
arr2 = [ 'foo', 'bar' ]  # Two elements
arr2 = []  # No elements

Alternatively, you can still create arrays using Array.new. This is not seen very often, at least without providing any argument to the constructor, but you can still do it. It is functionally equivalent to the empty list example above.

arr4 = Array.new  # No elements

Arrays of Strings

While it's not usually useful to throw a lot of alternative syntax and ways to do simple things at someone who is just learning, this one is so useful it's hard to ignore. Say you want to create an array of strings. They're the names of the people sitting around you. Already, you're thinking "my pinky is going to get a workout hitting that quote key, and it's real finger-fu to hit quotes and commas quickly, isn't there an easier way?" Yes, there is. Using the %w{ foo bar baz } syntax, you can create an array of strings very easily. Anything inside the braces (actually, most any character can be used there, but you'll usually see braces) is separated by whitespace, made into strings and stuffed into a new array. The following two examples produce equivalent arrays. The first needs a lot of typing, and typing quote characters. The second is the lazy (and therefore preferential) method. You'll also notice that it's a bit easier to read.

arr1 = [ 'Alice', 'Bob', 'Carol', 'Dave', 'Eve' ]
arr2 = %w{ Alice Bob Carol Dave Eve }

Indexing Arrays

OK, so you have an array, what do you do with it now? Let's start with getting objects out of an array. One way of doing this is to index the array using the index operator, which used square brackets. Index numbers start at zero, representing the first element in the array. They continue on up until the end of the array and, instead of raising an exception if you index the array past its bounds, nil will be returned.

a = %w{ foo bar baz }
puts a[0]  # foo
puts a[2]  # baz
puts a[3]  # Empty line (nil)

You can also index arrays with negative numbers. Indexing with -1 will return the last element, -2 the next to last, etc. This is convenient, otherwise you'd need to make a whole lot of subtractions using the length of the array if you index from the end of the array often.

a = %w{ foo bar baz }
puts a[-1]  # baz
puts a[-2]  # bar

Iterating Over Arrays

You can make arrays, you can index arrays, now you know how to iterate over arrays, right? Sure, you just start at 0, and keep incrementing and indexing until you hit the end, right? Wrong. Well, not wrong, that will work, but it's not very Ruby. In Ruby, you use the each method, which will iterate over each of the elements in the array and pass it to the block you give it. It's so simple to use, a single example should suffice.

a = %w{ foo bar baz }
a.each do|obj|
  puts obj

This is such a common idiom, you will likely never see an array be iterated using indexes (at least with code written by a Rubyist), and rarely see arrays iterated over in any other way.

More to Arrays

There's so much more to arrays. You'll be building arrays using push and pop, as well as using set operations (union, intersection, etc). You'll be sorting them, picking out unique objects, and all manner of operations. Ruby's Array operations are so capable, even LISP programmers may feel at home (and their parenthesis keys can finally take a break!).

©2014 About.com. All rights reserved.