Arrays

In this article by Loiane Groner, author of the book Learning JavaScript Data Structures and Algorithms, Second Edition, we will learn about arrays. An array is the simplest memory data structure. For this reason, all programming languages have a built-in array datatype. JavaScript also supports arrays natively, even though its first version was released without array support. In this article, we will dive into the array data structure and its capabilities.

An array stores values sequentially that are all of the same datatype. Although JavaScript allows us to create arrays with values from different datatypes, we will follow best practices and assume that we cannot do this(most languages do not have this capability).

(For more resources related to this topic, see here.)

Why should we use arrays?

Let's consider that we need to store the average temperature of each month of the year of the city that we live in. We could use something similar to the following to store this information:

var averageTempJan = 31.9;
var averageTempFeb = 35.3;
var averageTempMar = 42.4;
var averageTempApr = 52;
var averageTempMay = 60.8;

However, this is not the best approach. If we store the temperature for only 1 year, we could manage 12 variables. However, what if we need to store the average temperature for more than 1 year? Fortunately, this is why arrays were created, and we can easily represent the same information mentioned earlier as follows:

averageTemp[0] = 31.9;
averageTemp[1] = 35.3;
averageTemp[2] = 42.4;
averageTemp[3] = 52;
averageTemp[4] = 60.8;

We can also represent the averageTemp array graphically:

Learning JavaScript Data Structures and Algorithms - Second Edition

Creating and initializing arrays

Declaring, creating, and initializing an array in JavaScript is as simple, as shown by the following:

var daysOfWeek = new Array(); //{1}
var daysOfWeek = new Array(7); //{2}
var daysOfWeek = new Array('Sunday', 'Monday', 'Tuesday', 'Wednes"day', 'Thursday', 'Friday', 'Saturday'); //{3}

We can simply declare and instantiate a new array using the keyword new (line {1}). Also, using the keyword new, we can create a new array specifying the length of the array (line {2}). A third option would be passing the array elements directly to its constructor (line {3}).

However, using the new keyword is not best practice. If you want to create an array in JavaScript, we can assign empty brackets ([]),as in the following example:

var daysOfWeek = [];

We can also initialize the array with some elements, as follows:

var daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', "'Thursday', 'Friday', 'Saturday'];

If we want to know how many elements are in the array (its size), we can use the length property. The following code will give an output of 7:

console.log(daysOfWeek.length);

Accessing elements and iterating an array

To access a particular position of the array, we can also use brackets, passing the index of the position we would like to access. For example, let's say we want to output all the elements from the daysOfWeek array. To do so, we need to loop the array and print the elements, as follows:

for (var i=0; i<daysOfWeek.length; i++){
  console.log(daysOfWeek[i]);
}

Let's take a look at another example. Let's say that we want to find out the first 20 numbers of the Fibonacci sequence. The first two numbers of the Fibonacci sequence are 1 and 2, and each subsequent number is the sum of the previous two numbers:

var fibonacci = []; //{1}
fibonacci[1] = 1; //{2}
fibonacci[2] = 1; //{3}

for(var i = 3; i < 20; i++){
  fibonacci[i] = fibonacci[i-1] + fibonacci[i-2]; ////{4}
}

for(var i = 1; i<fibonacci.length; i++){ //{5}
  console.log(fibonacci[i]);           //{6}
}
  • So, in line {1}, we declared and created an array.
  • In lines {2} and {3}, we assigned the first two numbers of the Fibonacci sequence to the second and third positions of the array (in JavaScript, the first position of the array is always referenced by 0, and as there is no 0 in the Fibonacci sequence, we will skip it).
  • Then, all we have to do is create the third to the twentieth number of the sequence (as we know the first two numbers already). To do so, we can use a loop and assign the sum of the previous two positions of the array to the current position (line {4},starting from index 3 of the array to the 19th index).
  • Then, to take a look at the output (line {6}), we just need to loop the array from its first position to its length (line {5}).

We can use console.log to output each index of the array (lines {5} and {6}), or we can also use console.log(fibonacci) to output the array itself. Most browsers have a nice array representation in console.log.

If you would like to generate more than 20 numbers of the Fibonacci sequence, just change the number 20 to whatever number you like.

Adding elements

Adding and removing elements from an array is not that difficult; however, it can be tricky. For the examples we will use in this section, let's consider that we have the following numbers array initialized with numbers from 0 to 9:

var numbers = [0,1,2,3,4,5,6,7,8,9];

If we want to add a new element to this array (for example, the number 10), all we have to do is reference the latest free position of the array and assign a value to it:

numbers[numbers.length] = 10;

In JavaScript, an array is a mutable object. We can easily add new elements to it. The object will grow dynamically as we add new elements to it. In many other languages, such as C and Java, we need to determine the size of the array, and if we need to add more elements to the array, we need to create a completely new array; we cannot simply add new elements to it as we need them.

Using the push method

However, there is also a method called push that allows us to add new elements to the end of the array. We can add as many elements as we want as arguments to the push method:

numbers.push(11);
numbers.push(12, 13);

The output of the numbers array will be the numbers from 0 to 13.

Inserting an element in the first position

Now, let's say we need to add a new element to the array and would like to insert it in the first position, not the last one. To do so, first, we need to free the first position by shifting all the elements to the right. We can loop all the elements of the array, starting from the last position + 1 (length) and shifting the previous element to the new position to finally assign the new value we want to the first position (-1). Run the following code for this:

for (var i=numbers.length; i>=0; i--){
  numbers[i] = numbers[i-1];
}
numbers[0] = -1;

We can represent this action with the following diagram:

Learning JavaScript Data Structures and Algorithms - Second Edition

Using the unshift method

The JavaScript array class also has a method called unshift, which inserts the values passed in the method's arguments at the start of the array:

numbers.unshift(-2);
numbers.unshift(-4, -3);

So, using the unshift method, we can add the value -2 and then -3 and -4 to the beginning of the numbers array. The output of this array will be the numbers from -4 to 13.

Removing elements

So far, you have learned how to add values to the end and at the beginning of an array. Let's take a look at how we can remove a value from an array.

To remove a value from the end of an array, we can use the pop method:

numbers.pop();

The push and pop methods allow an array to emulate a basic stack data structure.

The output of our array will be the numbers from -4 to 12. The length of our array is 17.

Removing an element from first position

To remove a value from the beginning of the array, we can use the following code:

for (var i=0; i<numbers.length; i++){
  numbers[i] = numbers[i+1];
}

We can represent the previous code using the following diagram:

Learning JavaScript Data Structures and Algorithms - Second Edition

We shifted all the elements one position to the left. However, the length of the array is still the same (17), meaning we still have an extra element in our array (with an undefined value).The last time the code inside the loop was executed, i+1was a reference to a position that does not exist. In some languages such as Java, C/C++, or C#, the code would throw an exception, and we would have to end our loop at numbers.length -1.

As you can note, we have only overwritten the array's original values, and we did not really remove the value (as the length of the array is still the same and we have this extra undefined element).

Using the shift method

To actually remove an element from the beginning of the array, we can use the shift method, as follows:

numbers.shift();

So, if we consider that our array has the value -4 to 12 and a length of 17, after we execute the previous code, the array will contain the values -3 to 12 and have a length of 16.

The shift and unshift methods allow an array to emulate a basic queue data structure.

Adding and removing elements from a specific position

So far, you have learned how to add elements at the end and at the beginning of an array, and you have also learned how to remove elements from the beginning and end of an array. What if we also want to add or remove elements from any particular position of our array? How can we do this?

We can use the splice method to remove an element from an array by simply specifying the position/index that we would like to delete from and how many elements we would like to remove, as follows:

numbers.splice(5,3);

This code will remove three elements, starting from index 5 of our array. This means the numbers [5],numbers [6], and numbers [7] will be removed from the numbers array. The content of our array will be -3, -2, -1, 0, 1, 5, 6, 7, 8, 9, 10, 11, and 12 (as the numbers 2, 3, and 4 have been removed).

As with JavaScript arrays and objects, we can also use the delete operator to remove an element from the array, for example, remove numbers[0]. However, the position 0 of the array will have the value undefined, meaning that it would be the same as doing numbers[0] = undefined. For this reason, we should always use the splice, pop, or shift methods to remove elements.

Now, let's say we want to insert numbers 2 to 4 back into the array, starting from the position 5. We can again use the splice method to do this:

numbers.splice(5,0,2,3,4);

The first argument of the method is the index we want to remove elements from or insert elements into. The second argument is the number of elements we want to remove (in this case, we do not want to remove any, so we will pass the value 0 (zero)). And the third argument (onwards) are the values we would like to insert into the array (the elements 2, 3, and 4). The output will be values from -3 to 12 again.

Finally, let's execute the following code:

numbers.splice(5,3,2,3,4);

The output will be values from -3 to 12. This is because we are removing three elements, starting from the index 5, and we are also adding the elements 2, 3, and 4, starting at index 5.

Two-dimensional and multidimensional arrays

At the beginning of this article, we used the temperature measurement example. We will now use this example one more time. Let's consider that we need to measure the temperature hourly for a few days. Now that we already know we can use an array to store the temperatures, we can easily write the following code to store the temperatures over two days:

var averageTempDay1 = [72,75,79,79,81,81];
var averageTempDay2 = [81,79,75,75,73,72];

However, this is not the best approach; we can write better code! We can use a matrix (two-dimensional array) to store this information, in which each row will represent the day, and each column will represent an hourly measurement of temperature, as follows:

var averageTemp = [];
averageTemp[0] = [72,75,79,79,81,81];
averageTemp[1] = [81,79,75,75,73,72];

JavaScript only supports one-dimensional arrays; it does not support matrices. However, we can implement matrices or any multidimensional array using an array of arrays, as in the previous code. The same code can also be written as follows:

//day 1
averageTemp[0] = [];
averageTemp[0][0] = 72;
averageTemp[0][1] = 75;
averageTemp[0][2] = 79;
averageTemp[0][3] = 79;
averageTemp[0][4] = 81;
averageTemp[0][5] = 81;
//day 2
averageTemp[1] = [];
averageTemp[1][0] = 81;
averageTemp[1][1] = 79;
averageTemp[1][2] = 75;
averageTemp[1][3] = 75;
averageTemp[1][4] = 73;
averageTemp[1][5] = 72;

In the previous code, we specified the value of each day and hour separately. We can also represent this example in a diagram similar to the following:

Learning JavaScript Data Structures and Algorithms - Second Edition

Each row represents a day, and each column represents an hour of the day (temperature).

Iterating the elements of two-dimensional arrays

If we want to take a look at the output of the matrix, we can create a generic function to log its output:

function printMatrix(myMatrix) {
  for (var i=0; i<myMatrix.length; i++){
    for (var j=0; j<myMatrix[i].length; j++){
      console.log(myMatrix[i][j]);
    }
  }
}

We need to loop through all the rows and columns. To do this, we need to use a nested for loop in which the variable i represents rows, and j represents the columns.

We can call the following code to take a look at the output of the averageTemp matrix:

printMatrix(averageTemp);

Multi-dimensional arrays

We can also work with multidimensional arrays in JavaScript. For example, let's create a 3 x 3 matrix. Each cell contains the sum i (row) + j (column) + z (depth) of the matrix, as follows:

var matrix3x3x3 = [];
for (var i=0; i<3; i++){
  matrix3x3x3[i] = [];
  for (var j=0; j<3; j++){
    matrix3x3x3[i][j] = [];
    for (var z=0; z<3; z++){
      matrix3x3x3[i][j][z] = i+j+z;
    }
  }
}

It does not matter how many dimensions we have in the data structure; we need to loop each dimension to access the cell. We can represent a 3 x 3 x 3 matrix with a cube diagram, as follows:

Learning JavaScript Data Structures and Algorithms - Second Edition

To output the content of this matrix, we can use the following code:

for (var i=0; i<matrix3x3x3.length; i++){
  for (var j=0; j<matrix3x3x3[i].length; j++){
    for (var z=0; z<matrix3x3x3[i][j].length; z++){
      console.log(matrix3x3x3[i][j][z]);
    }
  }
}

If we had a 3 x 3 x 3 x 3 matrix, we would have four nested for statements in our code and so on.

References for JavaScript array methods

Arrays in JavaScript are modified objects, meaning that every array we create has a few methods available to be used. JavaScript arrays are very interesting because they are very powerful and have more capabilities available than primitive arrays in other languages. This means that we do not need to write basic capabilities ourselves, such as adding and removing elements in/from the middle of the data structure.

The following is a list of the core available methods in an array object. We have covered some methods already:

Method

Description

concat

This joins multiple arrays and returns a copy of the joined arrays

every

This iterates every element of the array, verifying a desired condition (function) until false is returned

filter

This creates an array with each element that evaluates to true in the function provided

forEach

This executes a specific function on each element of the array

join

This joins all the array elements into a string

indexOf

This searches the array for specific elements and returns its position

lastIndexOf

This returns the position of last item in the array that matches the search criteria

map

This creates a new array from a function that contains the criteria/condition and returns the elements of the array that match the criteria

reverse

This reverses the array so that the last items become the first and vice versa

slice

This returns a new array from the specified index

some

This iterates every element of the array, verifying a desired condition (function) until true is returned

sort

This sorts the array alphabetically or by the supplied function

toString

This returns the array as a string

valueOf

Similar to the toString method, this returns the array as a string

We have already covered the push, pop, shift, unshift, and splice methods. Let's take a look at these new ones.

Joining multiple arrays

Consider a scenario where you have different arrays and you need to join all of them into a single array. We could iterate each array and add each element to the final array. Fortunately, JavaScript already has a method that can do this for us named the concat method, which looks as follows:

var zero = 0;
var positiveNumbers = [1,2,3];
var negativeNumbers = [-3,-2,-1];
var numbers = negativeNumbers.concat(zero, positiveNumbers);

We can pass as many arrays and objects/elements to this array as we desire. The arrays will be concatenated to the specified array in the order that the arguments are passed to the method. In this example, zero will be concatenated to negativeNumbers, and then positiveNumbers will be concatenated to the resulting array. The output of the numbers array will be the values -3, -2, -1, 0, 1, 2, and 3.

Iterator functions

Sometimes, we need to iterate the elements of an array. You learned that we can use a loop construct to do this, such as the for statement, as we saw in some previous examples.

JavaScript also has some built-in iterator methods that we can use with arrays. For the examples of this section, we will need an array and also a function. We will use an array with values from 1 to 15 and also a function that returns true if the number is a multiple of 2 (even) and false otherwise. Run the following code:

var isEven = function (x) {
  // returns true if x is a multiple of 2.
  console.log(x);
  return (x % 2 == 0) ? true : false;
};
var numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

return (x % 2 == 0) ? true : false can also be represented as return (x % 2 == 0).

Iterating using the every method

The first method we will take a look at is the every method. The every method iterates each element of the array until the return of the function is false, as follows:

numbers.every(isEven);

In this case, our first element of the numbers array is the number 1. 1 is not a multiple of 2 (it is an odd number), so the isEven function will return false, and this will be the only time the function will be executed.

Iterating using the some method

Next, we have the some method. It has the same behavior as the every method; however, the some method iterates each element of the array until the return of the function is true:

numbers.some(isEven);

In our case, the first even number of our numbers array is 2 (the second element). The first element that will be iterated is the number 1; it will return false. Then, the second element that will be iterated is the number 2, which will return true, and the iteration will stop.

Iterating using forEach

If we need the array to be completely iterated no matter what, we can use the forEach function. It has the same result as using a for loop with the function's code inside it, as follows:

numbers.forEach(function(x){
  console.log((x % 2 == 0));
});

Using map and filter

JavaScript also has two other iterator methods that return a new array with a result. The first one is the map method, which is as follows:

var myMap = numbers.map(isEven);

The myMap array will have the following values: [false, true, false, true, false, true, false, true, false, true, false, true, false, true, false]. It stores the result of the isEven function that was passed to the map method. This way, we can easily know whether a number is even or not. For example, myMap[0] returns false because 1 is not even, and myMap[1] returns true because 2 is even.

We also have the filter method. It returns a new array with the elements that the function returned true, as follows:

var evenNumbers = numbers.filter(isEven);

In our case, the evenNumbers array will contain the elements that are multiples of 2: [2, 4, 6, 8, 10, 12, 14].

Using the reduce method

Finally, we have the reduce method. The reduce method also receives a function with the following parameters: previousValue, currentValue, index, and array. We can use this function to return a value that will be added to an accumulator, which will be returned after the reduce method stops being executed. It can be very useful if we want to sum up all the values in an array. Here's an example:

numbers.reduce(function(previous, current, index){
  return previous + current;
});

The output will be 120.

The JavaScript Array class also has two other important methods: map and reduce. The method names are self-explanatory, meaning that the map method will map values when given a function, and the reduce method will reduce the array containing the values that match a function as well. These three methods (map, filter, and reduce) are the base of the functional programming of JavaScript.

Summary

In this article, we covered the most-used data structure: arrays. You learned how to declare, initialize, and assign values as well as add and remove elements. You also learned about two-dimensional and multidimensional arrays as well as the main methods of an array, which will be very useful when we start creating our own algorithms.

You've been reading an excerpt of:

Learning JavaScript Data Structures and Algorithms - Second Edition

Explore Title
comments powered by Disqus