If you already know the basics of JavaScript arrays, it’s time to take your skills to the next level with more advanced topics. In this tutorial series, you’ll explore intermediate-level topics for programming with arrays in JavaScript.
In this tutorial, you’ll learn how to work with 2D arrays in JavaScript. JavaScript doesn’t have built-in support for 2D arrays. This isn’t a big deal because arrays in JavaScript can contain other arrays as elements. This means that we can create 2D arrays in JavaScript by creating an array of arrays.
Let’s go over some of the basics like initializing the 2D array and then implement additional features like getting and setting the values of elements in a 2D array.
Creating 2D Arrays in JavaScript
Regular arrays in JavaScript are one dimensional. We create regular arrays using literal notation or using the Array
constructor as shown below:
1 |
let numbers = [1, 2, 4, 59, 589, 126]; |
2 |
let names = new Array('Peter', 'Adam', 'Andy', 'Jake', 'Andrew'); |
3 |
|
4 |
console.log(numbers); |
5 |
// Outputs: [ 1, 2, 4, 59, 589, 126 ]
|
6 |
|
7 |
console.log(names); |
8 |
// Outputs: [ 'Peter', 'Adam', 'Andy', 'Jake', 'Andrew' ]
|
We can create 2D arrays in a similar way. Here is an example:
1 |
let matrix_a = [[1, 2, 4], [59, 589, 126], [34, 39, 27]]; |
2 |
let seating_arrangement = new Array(['Peter', 'Adam', 'Andy'], ['Jake', 'Andrew', 'Sam'], ['Jill', 'Jordan', 'Emma']); |
3 |
|
4 |
console.log(matrix_a); |
5 |
// Outputs: [ [ 1, 2, 4 ], [ 59, 589, 126 ], [ 34, 39, 27 ] ]
|
6 |
|
7 |
console.log(seating_arrangement); |
8 |
/* Outputs:
|
9 |
[
|
10 |
[ 'Peter', 'Adam', 'Andy' ],
|
11 |
[ 'Jake', 'Andrew', 'Sam' ],
|
12 |
[ 'Jill', 'Jordan', 'Emma' ]
|
13 |
]
|
14 |
*/
|
It’s important to remember that, unlike languages like C++, 2D arrays in JavaScript don’t have a fixed number of rows and columns. So if we want our array to be a rectangle, e.g. with all rows and columns being the same length, we need to make sure that the subarrays are all the same length.
In our example above, we created our matrix_a
matrix with three matrices. This gives three rows to our 2D array. Now each of those arrays had three elements of its own. This resulted in three columns in our 2D array. We could have restricted our third array to just two elements and matrix_a
it would still be a 2D array. However, it would be a jagged 2D array.
For the rest of this tutorial, we’ll focus on using 2D arrays with a fixed number of rows and columns. We define an array initialization function keeping these constraints in mind.
Initializing 2D arrays in JavaScript
We know that a 2D array consists of an array of arrays that make up its rows and columns. Creating and initializing a 2D array is simply a matter of repeatedly using the array constructor to fill the elements of our main array. The following function does this for us:
1 |
function create_2d_array(rows, columns, value = 0) { |
2 |
let array_2d = new Array(rows); |
3 |
|
4 |
for(let i = 0; i < rows; i++) { |
5 |
array_2d[i] = new Array(columns).fill(value); |
6 |
}
|
7 |
|
8 |
return array_2d; |
9 |
}
|
10 |
|
11 |
matrix_a = create_2d_array(3, 4, 1); |
12 |
console.log(matrix_a); |
13 |
// Outputs: [ [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ] ]
|
14 |
|
15 |
matrix_b = create_2d_array(4, 3, "Pie"); |
16 |
console.log(matrix_b); |
17 |
/* Outputs:
|
18 |
[
|
19 |
[ 'Pie', 'Pie', 'Pie' ],
|
20 |
[ 'Pie', 'Pie', 'Pie' ],
|
21 |
[ 'Pie', 'Pie', 'Pie' ],
|
22 |
[ 'Pie', 'Pie', 'Pie' ]
|
23 |
]
|
24 |
*/
|
Our function takes three arguments, the first being the number of rows which indicates how many arrays the parent array should contain. The second argument is the number of columns which determines how many elements there should be within each array. Finally, we have the third argument which is the value we want to set for each element in our 2D array.
Inside the function, we create a for
loop that iterates over all rows and fills the parent array element with new arrays. We call the fill()
method on each of these new arrays to initialize them with our specified value. All elements are set to 0 if no value is supplied by the user.
We can make our array initialization function shorter by using the built-in map()
method. Here is the code for our newest and shortest function:
1 |
function create_2d_array_with_map(rows, columns, value = 0) { |
2 |
let array_2d = new Array(rows).fill(0); |
3 |
return array_2d.map(() => new Array(columns).fill(value)); |
4 |
}
|
As you can see above, this will give us the same output as the original function. This time, we start as usual with our parent array of row items. However, we called the fill()
method to fill it with zeros. Afterwards, we called the map()
method on this array which returned a new array with all elements of the parent array filled with array of columns
number of items.
Some of you may now be wondering if we can make the array initialization function even shorter using the fill()
method twice instead of mapping the values as shown below:
1 |
function create_2d_array_wrong(rows, columns, value) { |
2 |
return new Array(rows).fill(new Array(columns).fill(value)); |
3 |
}
|
This will generate an array that looks the same as the previous ones, but with a subtle problem. Why the new Array(columns)
constructor is only called once, all column arrays will effectively be references to the exact same array.
This means that you won’t be able to update individual columns independently.
Get and set the values of elements in 2D arrays
You probably already know that we can access an array element at any index using the index value, and indexes are zero-based. Here is an example:
1 |
let names = new Array('Peter', 'Adam', 'Andy', 'Jake', 'Andrew'); |
2 |
console.log(names[3]); |
3 |
// Outputs: Jake
|
We got the fourth element in our array using the index value 3. Let’s try something similar with our 2D arrays.
1 |
let matrix_a = [[1, 2, 4], [59, 589, 126], [34, 39, 27]]; |
2 |
let seating_arrangement = new Array(['Peter', 'Adam', 'Andy'], ['Jake', 'Andrew', 'Sam'], ['Jill', 'Jordan', 'Emma']); |
3 |
|
4 |
console.log(matrix_a[1]); |
5 |
// Outputs: [ 59, 589, 126 ]
|
6 |
|
7 |
console.log(matrix_a[1][1]); |
8 |
// Outputs: 589
|
9 |
|
10 |
console.log(seating_arrangement[0]); |
11 |
// Outputs: [ 'Peter', 'Adam', 'Andy' ]
|
12 |
|
13 |
console.log(seating_arrangement[0][2]); |
14 |
// Outputs: Andy
|
15 |
|
As you can see, using a single index value gives us an element of the parent array and this element is actually an array itself. We need to provide another index value to get our element from the returned array.
Basically, the first index value gives us the array within which we should search for the element. We will call the first index value as row_index
. The second index value gives us the element we are looking for within our array returned by array. We will call the second index value as col_index
. We can use the following statement to access any element we want within our 2D array.
1 |
my_2d_array[row_idx][col_idx] |
This will become clearer from the following code snippet:
1 |
let seating_arrangement = new Array(['Peter', 'Adam', 'Andy'], ['Jake', 'Andrew', 'Sam'], ['Jill', 'Jordan', 'Emma']); |
2 |
|
3 |
console.table(seating_arrangement); |
4 |
/* Outputs:
|
5 |
┌─────────┬─────────┬──────────┬────────┐
|
6 |
│ (index) │ 0 │ 1 │ 2 │
|
7 |
├─────────┼─────────┼──────────┼────────┤
|
8 |
│ 0 │ 'Peter' │ 'Adam' │ 'Andy' │
|
9 |
│ 1 │ 'Jake' │ 'Andrew' │ 'Sam' │
|
10 |
│ 2 │ 'Jill' │ 'Jordan' │ 'Emma' │
|
11 |
└─────────┴─────────┴──────────┴────────┘
|
12 |
*/
|
13 |
|
14 |
console.log(seating_arrangement[0][2]); |
15 |
// Outputs: Andy
|
16 |
|
17 |
|
18 |
console.log(seating_arrangement[2][0]); |
19 |
// Outputs: Jill
|
Using console.table()
registering our 2D arrays makes them easier to understand.
In the first case, we got the element from the first row (index 0) and the third column (index 2). This gave us the value Andy. Similarly, we got Jill looking at the third row and first column.
Now that you know how to access the values of items in a particular row or index, it’s easy to set a value for that item using a simple assignment. Here is an example:
1 |
let seating_arrangement = new Array(['Peter', 'Adam', 'Andy'], ['Jake', 'Andrew', 'Sam'], ['Jill', 'Jordan', 'Emma']); |
2 |
|
3 |
console.table(seating_arrangement); |
4 |
/* Outputs:
|
5 |
┌─────────┬─────────┬──────────┬────────┐
|
6 |
│ (index) │ 0 │ 1 │ 2 │
|
7 |
├─────────┼─────────┼──────────┼────────┤
|
8 |
│ 0 │ 'Peter' │ 'Adam' │ 'Andy' │
|
9 |
│ 1 │ 'Jake' │ 'Andrew' │ 'Sam' │
|
10 |
│ 2 │ 'Jill' │ 'Jordan' │ 'Emma' │
|
11 |
└─────────┴─────────┴──────────┴────────┘
|
12 |
*/
|
13 |
|
14 |
seating_arrangement[0][2] = 'Olivia'; |
15 |
|
16 |
seating_arrangement[2][0] = 'Ava'; |
17 |
|
18 |
console.table(seating_arrangement); |
19 |
/* Outputs:
|
20 |
┌─────────┬─────────┬──────────┬──────────┐
|
21 |
│ (index) │ 0 │ 1 │ 2 │
|
22 |
├─────────┼─────────┼──────────┼──────────┤
|
23 |
│ 0 │ 'Peter' │ 'Adam' │ 'Olivia' │
|
24 |
│ 1 │ 'Jake' │ 'Andrew' │ 'Sam' │
|
25 |
│ 2 │ 'Ava' │ 'Jordan' │ 'Emma' │
|
26 |
└─────────┴─────────┴──────────┴──────────┘
|
27 |
*/
|
Remember when I mentioned earlier that creating 2D arrays with two successive calls to fill()
method will create problems due to all elements referencing the same object? You can verify this yourself with the following code snippet:
1 |
function create_2d_array_wrong(rows, columns, value) { |
2 |
return new Array(rows).fill(new Array(columns).fill(value)); |
3 |
}
|
4 |
|
5 |
matrix_a = create_2d_array_wrong(3, 4, 1); |
6 |
console.log(matrix_a); |
7 |
// Outputs: [ [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ] ]
|
8 |
|
9 |
matrix_a[0][1] = 4; |
10 |
|
11 |
console.log(matrix_a); |
12 |
// Outputs: [ [ 1, 4, 1, 1 ], [ 1, 4, 1, 1 ], [ 1, 4, 1, 1 ] ]
|
We only changed the value of the item in the first row and second column. However, the value in the second column has been updated for all rows.
Setting entire rows or column values
Now we will learn how to replace the value of the entire row or column into a 2D array.
Replacing row values is simple because the entire row is basically a single array. The only constraint we will place on this replacement is that the replacement array must have the same number of elements as the original array. Here is our function that does the substitution:
1 |
function replace_row(array_2d, row_array, row_idx) { |
2 |
let array_2d_columns = array_2d[0].length; |
3 |
if(row_array.length == array_2d_columns) { |
4 |
array_2d[row_idx] = row_array; |
5 |
}
|
6 |
}
|
7 |
|
8 |
let seating_arrangement = new Array(['Peter', 'Adam', 'Andy'], ['Jake', 'Andrew', 'Sam'], ['Jill', 'Jordan', 'Emma']); |
9 |
|
10 |
console.table(seating_arrangement); |
11 |
/* Outputs:
|
12 |
┌─────────┬─────────┬──────────┬────────┐
|
13 |
│ (index) │ 0 │ 1 │ 2 │
|
14 |
├─────────┼─────────┼──────────┼────────┤
|
15 |
│ 0 │ 'Peter' │ 'Adam' │ 'Andy' │
|
16 |
│ 1 │ 'Jake' │ 'Andrew' │ 'Sam' │
|
17 |
│ 2 │ 'Jill' │ 'Jordan' │ 'Emma' │
|
18 |
└─────────┴─────────┴──────────┴────────┘
|
19 |
*/
|
20 |
|
21 |
replace_row(seating_arrangement, ['Olivia', 'Ava', 'Sophia'], 1); |
22 |
|
23 |
console.table(seating_arrangement; |
24 |
/* Outputs:
|
25 |
┌─────────┬──────────┬──────────┬──────────┐
|
26 |
│ (index) │ 0 │ 1 │ 2 │
|
27 |
├─────────┼──────────┼──────────┼──────────┤
|
28 |
│ 0 │ 'Peter' │ 'Adam' │ 'Andy' │
|
29 |
│ 1 │ 'Olivia' │ 'Ava' │ 'Sophia' │
|
30 |
│ 2 │ 'Jill' │ 'Jordan' │ 'Emma' │
|
31 |
└─────────┴──────────┴──────────┴──────────┘
|
32 |
*/
|
Replacing column values will require us to iterate through all the rows because each item in a column comes from a different array. We will also include a condition that matches the number of rows and the length of the replacement column array. Here is the code of our function:
1 |
function replace_column(array_2d, column_array, col_idx) { |
2 |
if(column_array.length == array_2d.length) { |
3 |
for(let i = 0; i < column_array.length; i++) { |
4 |
array_2d[i][col_idx] = column_array[i]; |
5 |
}
|
6 |
}
|
7 |
}
|
8 |
|
9 |
let seating_arrangement = new Array(['Peter', 'Adam', 'Andy'], ['Jake', 'Andrew', 'Sam'], ['Jill', 'Jordan', 'Emma']); |
10 |
console.table(seating_arrangement); |
11 |
/* Outputs:
|
12 |
┌─────────┬─────────┬──────────┬────────┐
|
13 |
│ (index) │ 0 │ 1 │ 2 │
|
14 |
├─────────┼─────────┼──────────┼────────┤
|
15 |
│ 0 │ 'Peter' │ 'Adam' │ 'Andy' │
|
16 |
│ 1 │ 'Jake' │ 'Andrew' │ 'Sam' │
|
17 |
│ 2 │ 'Jill' │ 'Jordan' │ 'Emma' │
|
18 |
└─────────┴─────────┴──────────┴────────┘
|
19 |
*/
|
20 |
|
21 |
replace_column(seating_arrangement, ['Olivia', 'Ava', 'Sophia'], 1); |
22 |
console.table(seating_arrangement); |
23 |
/* Outputs:
|
24 |
┌─────────┬─────────┬──────────┬────────┐
|
25 |
│ (index) │ 0 │ 1 │ 2 │
|
26 |
├─────────┼─────────┼──────────┼────────┤
|
27 |
│ 0 │ 'Peter' │ 'Olivia' │ 'Andy' │
|
28 |
│ 1 │ 'Jake' │ 'Ava' │ 'Sam' │
|
29 |
│ 2 │ 'Jill' │ 'Sophia' │ 'Emma' │
|
30 |
└─────────┴─────────┴──────────┴────────┘
|
31 |
*/
|
Final thoughts
In this tutorial, we’ve covered the basics of 2D arrays in JavaScript. Their is no built in support for 2D arrays in JavaScript. However, we can still create them easily by initializing an array of arrays. This tutorial showed us several ways to initialize 2D arrays. We’ve also learned how to get or set the value of individual elements in our 2D array or replace the entire row or column at once.
You can also use the built-in array methods with these 2D arrays to implement additional functionality such as 2D array splicing or slicing.