RichieAHB
RichieAHB

Reputation: 2088

Cleanest way to check all sub-arrays are defined

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

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1075199

"Cleanest" is a subjective term, but three possibilities for you:

  1. Use JavaScript's curiously powerful || operator:

    count += (this.data[i-1] || [])[j-1] || 0;
    

    That works for two reasons:

    1. In JavaScript, accessing an array index that doesn't exist returns undefined. It doesn't cause an error.

    2. 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;
    
  2. 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:

  3. 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

Related Questions