Reputation: 73908
When there is a single dimension array, it is easy to check whether it is defined, by either simple calling arr[6]
which will return undefined
if such property does not exist or calling typeof arr[6] === undefined
.
The problem is, that in my case I have arr[5][1][6][2][5][3][7]
, where arr[5]
can be non existent, or arr[5][1]
, etc. Which will naturally trigger error: TypeError: Cannot read property [..]
One solution is to write many IF statements. However, is there any better solution, that'd simple allow me to check whether arr[5][1][6][2][5][3][7]
is defined?
Upvotes: 0
Views: 648
Reputation: 6209
A pragmatic approach would be to break this problem down into its component parts; look at what data is known and the tools you have at hand.
So, what do we know - well we know the keys that we want to inspect, in the case of checking if arr[5][1][6][2][5][3][7]
is defined. Now ask yourself, what tools do we have in JavaScript? To check if an Array index is defined we can compare against null, ie:
if (array[index] === null) {
return false
}
If we were to try and write this code, one of the first things that should come to mind is to simply walk through each key, in order: eg:
if (array[5] === null) {
return false;
} else if (array[5][1] === null) {
return false
} ...snip...
// Good news, it's defined!
return true
Obviously this approach can be improved, it requires a tonne of duplicated code to be written out, it's inflexible and not reusable. If you ever find yourself doing the same thing over and over, you probably have a good candidate for a loop construct. In order for a loop you need a variant, something that will change with each repetition - in the example above the variant is the right most element of the nested array we are inspecting. First, let's start by listing our variants out:
var variants = [ 5, 1, 6, 2, 5, 3, 7 ];
for (var i = 0; i < variants.length; i++) {
console.log("variant: " + variants[i]);
}
Where, do we go from here? Well things get a bit harder, you need to understand how Arrays are passed by reference in JavaScript and exploit that in the loop body; ultimately you may end up with something like this:
function arrayDimensionsExist(source, dimensions) {
var currentDepth = source;
for (var i = 0; i < dimensions.length; i++) {
var key = dimensions[i];
if (currentDepth[key] === null) {
return false;
} else {
currentDepth = source[key];
}
}
return true;
}
Upvotes: 1
Reputation: 2607
By using a try/catch block you can check if the element can be accessed.
var x;
try {
x = arr[5][1][6][2][5][3][7];
} catch(TypeError)
{
// the element cannot be accessed
x = undefined;
}
Then it's easy enough to check if 'x' is defined or not using an if statement.
Upvotes: 1
Reputation: 129849
There's no solution built-in to the language, but you could handle it with a function like this:
var verifyIndexes = function(target) {
var current = target;
for (i = 1; i < arguments.length; i++) {
if (arguments[i] in current) {
current = current[arguments[i]];
} else {
return false;
}
}
return true;
}
var myArray = [[[1, 2, 3], 4], 5];
console.log(verifyIndexes(myArray, 0)); // true
console.log(verifyIndexes(myArray, 0, 0, 0)); // true
console.log(verifyIndexes(myArray, 0, 0, 3)); // false
console.log(verifyIndexes(myArray, 0, 1)); // true
console.log(verifyIndexes(myArray, 0, 2)); // false
Upvotes: 0
Reputation: 43253
Since this seemed like an interesting problem, I wrote this function to solve it in a nice an non-exceptional way :)
var deepCheck = function(arr, indexes) {
var level = arr;
while(indexes.length) {
var v = indexes.shift()
if(!level[v]) {
return false;
}
level = level[v];
}
return true;
};
Now say you have this:
arr[foo][bar][baz];
You would check it using...
deepCheck(arr, [foo, bar, baz]);
Maybe I should point out that I do kind of agree that if you indeed have very very long arrays like that, it does sound like a design issue.
Upvotes: 1
Reputation: 67447
Put the code accessing it between try
and catch
. If it works, it works, if not you get a nice exception and you can react accordingly.
As a side note, I shudder to think of what prompted you to design your system like that...
Upvotes: 0
Reputation: 82634
I can't think of anything better than:
var defined = false;
try {
defined = !!arr[5][1][6][2][5][3][7]
} catch(e)
{
// nothing
}
But seriously bad design.
Upvotes: 2