Reputation: 2088
I was just writing a little game of life script, seen as I'd never really done it. I have created a matrix array that has sub arrays of columns, each containing the values of each row in that column. When I loop through to check the neighbours I want to count them like the below:
var count = 0;
count += this.data[i-1][j-1];
count += this.data[i-1][i];
count += this.data[i-1][j+1];
count += this.data[i][j-1];
count += this.data[i][j+1];
count += this.data[i+1][j-1];
count += this.data[i+1][i];
count += this.data[i+1][j+1];
Obviously on the i-1
and i+1
indexes will cause a problem at the beginning and end of the arrays. I can check for undefined on the value of the rows (the deepest value) like so:
count += typeof this.data[i-1][j-1] !== 'undefined' ? this.data[i-1][j-1] : 0;
But if the columns array is undefined obviously it will error and I can't check this without writing a few more lines. Is there anyway I can catch this error in this one line, or is there a quicker way to get this data. I just don't want lots of try/catches or if/elses to account for the edges of the matrices?
I know I could remove the sub-array structure and just have one long array of data but I was just curious about efficient ways of dealing with this structure.
Upvotes: 1
Views: 44
Reputation: 1075199
"Cleanest" is a subjective term, but three possibilities for you:
Use JavaScript's curiously powerful ||
operator:
count += (this.data[i-1] || [])[j-1] || 0;
That works for two reasons:
In JavaScript, accessing an array index that doesn't exist returns undefined
. It doesn't cause an error.
Unlike many programming languages, JavaScript's ||
returns its first operand if that operand is truthy and its second operand if not, rather than a boolean. Truthy values are values that aren't falsey; falsey values are 0
, undefined
, null
, ""
, NaN
, and of course false
. So 1 || 0
is 1
, undefined || 0
is 0
, and 0 || 0
is also 0
.
Note that the || []
part of that won't create an array unless the this.data[i-1]
part is undefined
. But if you're worried about creating temporary arrays like that, you could have just one defined throughout your script (var blank = [];
) and then use it:
count += (this.data[i-1] || blank)[j-1] || 0;
Define your arrays (both the "vertical" one and all the "horizontal" ones) two elements too big and set the values around the edges to 0. Then loop from 1
to < length - 1
, and you don't have to worry about going out of bounds because the -1
case will take you to the 0th element, which has the value 0
, and the +1
case will take you to the length-1
element, which also has the value 0
. This offers quite clean code at the expense of a small bit of extra memory. Or:
Have a function to get the value which checks the coordinates and returns 0
if either is invalid. This offers quite clean code at the expense of a small bit of added overhead.
Upvotes: 2