What are multidimensional arrays?
Have you ever encountered matrices in those old days at school in your mathematics classes? A matrix is essentially a two-dimensional structure to hold numbers that we could process in a multitude of ways.
In programming, when it became apparent that supporting matrices was paramount in code, the idea of two-dimensional, or 2D, arrays sprung up.
A 2D array is simply an array of elements, which in the case of a matrix are usually numbers, where accessing an element typically requires two indexing operations.
Similarly, a 3D array is an array where we typically need to access 3 indices before reaching a given end value.
In general,
Languages such as C and C++ truly support multidimensional arrays out of the box.
While defining an array in these languages, we get to further define its number of dimensions upfront. Thereafter, the compiler itself normalizes every sequence of indexing operations to one single indexing operation based on simple arithmetic.
Coming back to the topic, many modern-day dynamic languages — the likes of JavaScript, Python, and even PHP — don't, however, support true multidimensional arrays. They instead support another similar idea that could be used to emulate multidimensional arrays. That idea is of jagged arrays.
As you can see, a jagged array is NOT a flat array consisting of scalar values as is the case with a multidimensional array. But thanks to this idea of nested arrays in a jagged array, we can try to replicate multidimensional arrays using it.
An indexing operation on a jagged array takes us to one of its constituent arrays, then another indexing operation takes us to one of that array's constituent arrays, and so on until we reach a final value.
Reiterating the fact about PHP, it does NOT support true multidimensional arrays.
But since an element of an array in PHP could be any valid value, when that value is an array itself, we have a jagged array, i.e. an emulation of a multidimensional array — specifically of a 2D array.
Let's now create some multidimensional arrays in PHP.
Representing matrices
Consider the following 2 x 2 matrix of integers:
Our goal is to represent it in PHP using an array and then perform the scalar multiplication matrix operation on it.
So first, let's get to the representation. Since a 2D array in PHP is just an array of arrays, there isn't anything new to learn syntactically — just initialize an array with arrays themselves.
<?php
$matrix = [
// Code to go here.
];
The matrix above has two rows and so we'll need two elements in our $matrix
array. Next, each of these arrays need to have two elements as well because that's the number of columns of the matrix. Altogether, we get to the following code:
<?php
$matrix = [
[1, 10],
[3, 7]
];
Simple.
With the representation done, now we need to perform the given scalar multiplication operation. Fortunately, it's superbly easy — just multiply each element by the given value.
For example, the scalar multiple of the 2x2 matrix above for the number 2, would be as follows.
Given that we want to modify the original $matrix
array, we'll use a basic set of nested for
loops with the counter variables $i
and $j
, respectively.
Something like this:
<?php
$matrix = [
[1, 10],
[3, 7]
];
for ($i = 0, $len = count($matrix); $i < $len; $i++) {
for ($j = 0; $j < $len; $j++) {
$matrix[$i][$j] *= 2;
}
}
Time to test whether our loop works as expected:
<?php
$matrix = [
[1, 10],
[3, 7]
];
for ($i = 0, $len = count($matrix); $i < $len; $i++) {
for ($j = 0; $j < $len; $j++) {
$matrix[$i][$j] *= 2;
}
}
print_r($matrix);
And it indeed does.
We can even use foreach
here but we'll do that later in this chapter owing to the fact that it requires usage of references in both the loops.
Iteration over 2D array using foreach
We learnt about the foreach
loop in detail in the PHP Control Flow — foreach
chapter. It's used to provide us with a much simpler way to iterate over a given array.
Using foreach
, it's obviously possible to iterate over a multidimensional array, but we need to be careful when doing so if we are trying to make modifications to the underlying array.
Let's see what this means.
Given the following $matrix
array:
<?php
$matrix = [
[1, 10],
[3, 7],
];
here's how we could iterate over it and print each row, by iterating over each number therein:
<?php
$matrix = [
[1, 10],
[3, 7],
];
foreach ($matrix as $row) {
foreach ($row as $num) {
echo "$num ";
}
echo "\n";
}
Nothing complicated at all.
But now let's say we want to perform the same scalar multiplication operation that we did before, albeit switch to using foreach
instead.
Let's do it:
<?php
$matrix = [
[1, 10],
[3, 7],
];
// Perform scalar multiplication using foreach.
foreach ($matrix as $row) {
foreach ($row as &$num) {
$num *= 2;
}
}
print_r($matrix);
What? The output doesn't seem to confirm that scalar multiplication has been performed.
Have we made $num
a reference variable, since we need its modification to trigger the modification of the corresponding array element? Yes, we have made it one. Then what?
What could possibly be wrong here? Think about it.
Well, we've already discussed such a similar problem in the PHP Control Flow — foreach
chapter. The problem is caused by the fact that at every stage of the outer foreach
, the loop's variable $row
that gets assigned the next item (which is an array) of $matrix
receives a copy of that item.
So in the code above, each $row
does NOT actually refer to the corresponding array in $matrix
representing that row; instead, it refers to a copy of that row.
How to solve this problem? Simple — use references.
Let's modify the code above by labelling $row
to be a reference variable. In this way, it'll receive the actual underlying array in each iteration of the loop.
Altogether, we get to the following code:
<?php
$matrix = [
[1, 10],
[3, 7],
];
// Perform scalar multiplication using foreach.
foreach ($matrix as &$row) {
foreach ($row as &$num) {
$num *= 2;
}
}
print_r($matrix);
Perfect! We are all good now.