14 – Arrays
Sometimes we need to store a list of values. Who's coming to dinner? What were the team's scores for the season?
Arrays are ordered lists of data. Each item in the list is called an element, which we can access by the element's index.
var guests = ["Alice", "Charles", "Dave", "Bob"];
var scores = [10, 15, 12, 17, 3, 11, 23];
var bananas = [true, 0, "Today"]; // Yes! We Have No Bananas
Once we have an array, we can loop over its elements the same way we loop over a string's characters. We can add and remove elements, change each element, and even sort the array any way we like.
Above we use square brackets to denote an Array literal. There are other ways to create arrays, but this is the most useful.
Array Elements
If we try to output an array, we'll see the contents of the array as a string:
console.log(guests); // "Alice,Charles,Dave,Bob"
console.log(scores); // "10,15,12,17,3,11,23"
Note how the order of the elements is kept intact; no sorting takes place.
We can access elements of an array by index:
guests[0]; // "Alice"
guests[2]; // "Dave"
We can find out how many elements are in an array with the length
property:
scores.length; // 7
for (var i = 0; i < scores.length; i += 1) {
console.log(i + ": " + scores[i]);
}
Creating an Array from a String
We can create an array from a string with the split
method:
String.split( delimiter )
var guests = "Alice,Charles,Dave,Bob".split(',');
var scores = "9 15 12 17 3 11 23".split(' ');
guests.length; // 4
scores.length; // 7
Creating a String from an Array
Usually, when an array is output, it will be coerced into a string:
alert(guests); // "Alice,Charles,Dave,Bob"
alert(scores); // "9,15,12,17,3,11,23"
However, when using console.log
or the like, the console panel will often show you the array in literal form.
We get more control over converting an array to a string using the join
method:
Array.join( separator = ',' )
It coerces each element's value to a string, and concatenates them, separating each element string with the separator, which defaults to ,
.
scores.join(); // "9,15,12,17,3,11,23"
scores.join(" "); // "9 15 12 17 3 11 23"
guests.join(', '); // "Alice, Charles, Dave, Bob"
guests.join(' & '); // "Alice & Charles & Dave & Bob"
Modifying an Array
We can modify an element in an array:
guests[2] = "Steve";
guests; // "Alice,Charles,Steve,Bob"
scores[0] = 9;
scores; // "9,15,12,17,3,11,23"
We can add elements onto the end of an array with the push
method:
scores.push(11);
scores; // "9,15,12,17,3,11,23,11"
scores.length; // 8
guests.push("Elaine", "Frodo");
guests; // "Alice,Charles,Steve,Bob,Elaine,Frodo"
guests.length; // 6
JavaScript can also take elements off the end of an array with pop
:
var lastGuest = guests.pop();
guests; // "Alice,Charles,Steve,Bob,Elaine"
guests.length; // 5
lastGuest; // "Frodo"
We can also add and remove elements from the start of an array with unshift
and shift
:
guests.unshift("Gollum", "Samwise", "Merry", "Pippin");
guests; // "Gollum,Samwise,Merry,Pippen,Alice,Charles,Steve,Bob,Elaine"
guests.length; // 9
var unableToAttend = guests.shift();
unableToAttend; // "Gollum"
Deleting and adding elements into an array is possible with splice
:
Array.splice( start, deleteCount [, item1 [, item2...]] )
guests.splice(5, 2);
guests; // "Samwise,Merry,Pippen,Alice,Charles,Elaine"
guests.splice(3,0,"Frodo");
guests; // "Samwise,Merry,Pippen,Frodo,Alice,Charles,Elaine"
guests.splice(1,0,"Bilbo","Gandalf");
guests; // "Samwise,Bilbo,Gandalf,Merry,Pippen,Frodo,Alice,Charles,Elaine"
The modify functions
unshift shift
│ ▲
│ │
┌──▼──────┴─┐
0│ Frodo │
├───────────┤
1│ Sam │ ───▶
├───────────┤ splice
2│ Merry │ ◀───
├───────────┤
3│ Pippin │
└─▲───────┬─┘
│ │
│ ▼
push pop
Sorting an array
The sort
method is a very interesting one. It sorts an array's elements into order.
Array.sort( [ compareFunction ]);
var fruit = ['apple', 'banana', 'Cherry'];
fruit.sort();
fruit; // "Cherry,apple,banana" <-- not sorted alphabetically
var ages = [15, 20, 2, 11, 9, 10];
ages.sort();
ages; // "10,11,15,2,20,9" <-- not sorted numerically
But as you can see, it doesn't really work the way you want. sort
coerces each element into a string, then sorts the strings according to Unicode code point order. In Unicode, Number characters are before the letters, and capital letters are before the lower case letters. At least the numbers and letters are in numeric and alphabetical order.
So sort
is case sensitive to a tee, and prefers numbers to letters. However, we can teach sort
in many different ways, by providing it a compare function. This function accepts two parameters, often called a
and b
, and returns -1
if a < b
, or 1
if a > b
, or 0
if they are equal.
function compare(a, b) {
console.log(a + " vs " + b);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
// by elimination, a must be equal to b.
return 0;
}
Of course, the above compare function does exactly the same thing as sort
by itself, except it does not coerce elements to strings.
fruit.sort(compare); // ["Cherry", "apple", "banana"]
console.log('---');
ages.sort(compare); // [2, 9, 10, 11, 15, 20] <-- numerically ascending!
Output:
Cherry vs apple
apple vs banana
---
20 vs 15
20 vs 11
15 vs 11
20 vs 10
15 vs 10
11 vs 10
20 vs 9
15 vs 9
11 vs 9
10 vs 9
20 vs 2
15 vs 2
11 vs 2
10 vs 2
9 vs 2
Please note that we do not call compare
when we pass it to sort
. sort
will call compare
each time it needs to compare two elements.
// WRONG:
fruit.sort(compare());
// CORRECT:
fruit.sort(compare);
Aside: Functions in JavaScript are fully fledged values. You can put them in variables and pass them as arguments and even have a function return a function. In computer programming, this is called an anonymous function
Sorting Arrays of Numbers
The above function is a good explanation, but if we wish to sort numerically, this compareNumbers
function is much better.
function compareNumbersAscending(a, b) {
return a - b;
}
function compareNumbersDescending(a, b) {
return b - a;
}
var ages = [15, 20, 2, 11, 9, 10];
ages.sort(compareNumbersAscending); // [2, 9, 10, 11, 15, 20]
ages.sort(compareNumbersDescending); // [20, 15, 11, 10, 9, 2]
The compareNumbersAscending
still returns a positive or negative number, or zero. compareNumbersDescending
does the same thing, only larger numbers come first.
Sorting Arrays of Strings Alphabetically
Here are some compare functions for sorting arrays of strings, case insensitively:
function compareStringsAscending(a, b) {
return a.toLowerCase() - b.toLowerCase();
}
var fruit = ["apple", "banana", "Cherry", "dates"];
fruit.sort(compareStringsAscending);
Notes about Sorting
Sorting is one of the more processor-intensive things you can ask a computer to do, and the more elements to sort, the longer it takes. While sorting ~100 things shouldn't take a lot of time on today's computers, doing that sort unnecessarily could slow the program down.
JavaScript should use an appropriately efficient sorting algorithm (which is these days is Quick Sort), and we just need to provide the compare function.
- Computerphile: Getting Sorted - How computer sorts work on paper.
- Sorting Algorithms - animations on how different computer sort methods work.
- Fisher–Yates Shuffle - an explanation on how to de-sort or shuffle an array efficiently in JavaScript.
- 15 Sorting Algorithms in 6 Minutes - visual examples of how sorting algorithms work. (turn down your speakers)
Exercises
Reading Arrays
- Write a function that takes an array of elements and returns true if all the elements are strings.
- Write one function for each of the following that takes an array of unsorted numbers and returns a number:
- the average or mean (sum of elements ÷ count of elements)
- the minimum number (smallest element)
- the maximum number (largest element)
- the median (the middle element when sorted)
- Extra for experts: the mode (the element that appears most frequently,
false
if nothing is repeated)
- Write a function that takes an array of people's names
['Alice', 'Bob', 'Charles']
and output a proper English sentence:"Alice, Bob, and Charles"
. See how every name is separated with a comma, except the last one which is preceded by 'and'. - Using an array of ranks and an array of suits, write a set of nested loops that outputs every playing card: Ranks: Ace, 2—10, Jack, Queen, King. Suits: Clubs, Diamonds, Hearts, Spades.
- Extra for experts: do it using
%
and a singlefor
loop.
- Extra for experts: do it using
- Using an array of months and an array of days in each month, write a program that outputs each day of the year:
1 January
2 January
3 January
…
30 January
31 January
1 February
2 February
…
29 November
30 November
1 December
…
31 December
Creating Arrays
- Write a function that takes an array of string elements and returns a new array of only the elements that contain strings longer than 5 characters.
- Write a function that takes an array of numbers and returns a new array of each element squared (i.e. 3 squared = 3² = 3 ✕ 3 = 9), (e.g.
[3, 10, 42]
=>[9, 100, 1764]
)
Sorting Arrays
- Write a function that sorts an array of numbers numerically, with largest numbers coming last (ascending).
- Write a function that takes an array of string elements and sorts the array by length of string with longest strings coming first (descending).
- Write a function that takes an array of string elements and sorts the array by each element's vowel count, with highest vowel count coming last (ascending).