Reputation: 7259
I have an array with nested arrays that looks like this:
var tw = [[3, 0], [11, 0], [3, 14], [11, 14]];
When I try and find if the array tw
contains a passed in array, I always get a result of -1.
For example:
var test = $.inArray([3, 0], tw);
var test2 = tw.indexOf([3, 0]);
both return -1, even though the first object in the array is [3,0]
How do I find out if a specific array of arrays is contained in my array?
Oh, and I've only tested it on IE9 so far.
Upvotes: 9
Views: 7976
Reputation: 702
Why not keep it simple?
function indexOfCustom (parentArray, searchElement) {
for ( var i = 0; i < parentArray.length; i++ ) {
if ( parentArray[i][0] == searchElement[0] && parentArray[i][1] == searchElement[1] ) {
return i;
}
}
return -1;
}
Upvotes: 0
Reputation: 11774
For infinite nested search:
function indexOfArr(arr1, fnd1) {
var i, len1;
//compare every element on the array
for (i = 0, len1 = arr1.length; i < len1; i++) {
//index missing, leave to prevent false-positives with 'undefined'
if (!(i in arr1)) {
continue;
}
//if they are exactly equal, return the index
if (elementComparer(arr1[i], fnd1)) {
return i;
}
}
//no match found, return false
return -1;
}
function elementComparer(fnd1, fnd2) {
var i, len1, len2, type1, type2, iin1, iin2;
//store the types of fnd1 and fnd2
type1 = typeof fnd1;
type2 = typeof fnd2;
//unwanted results with '(NaN!==NaN)===true' so we exclude them
if (!((type1 == "number" && type2 == "number") && (fnd1 + "" == "NaN" && fnd2 + "" == "NaN"))) {
//unwanted results with '(typeof null==="object")===true' so we exclude them
if (type1 == "object" && fnd1 + "" != "null") {
len1 = fnd1.length;
//unwanted results with '(typeof null==="object")===true' so we exclude them
if (type2 == "object" && fnd2 + "" != "null") {
len2 = fnd2.length;
//if they aren't the same length, return false
if (len1 !== len2) {
return false;
}
//compare every element on the array
for (i = 0; i < len1; i++) {
iin1 = i in fnd1;
iin2 = i in fnd2;
//if either index is missing...
if (!(iin1 && iin2)) {
//they both are missing, leave to prevent false-positives with 'undefined'
if (iin1 == iin2) {
continue;
}
//NOT the same, return false
return false;
}
//if they are NOT the same, return false
if (!elementComparer(fnd1[i], fnd2[i])) {
return false;
}
}
} else {
//NOT the same, return false
return false;
}
} else {
//if they are NOT the same, return false
if (fnd1 !== fnd2) {
return false;
}
}
}
//if it successfully avoided all 'return false', then they are equal
return true;
}
Notes:
Upvotes: 2
Reputation: 324707
That's because you're searching for a different object. indexOf()
uses strict equality comparisons (like the ===
operator) and [3, 0] === [3, 0]
returns false.
You'll need to search manually. Here's an example using a more generic indexOf()
function that uses a custom comparer function (with an improvement suggested by @ajax333221 in the comments):
// Shallow array comparer
function arraysIdentical(arr1, arr2) {
var i = arr1.length;
if (i !== arr2.length) {
return false;
}
while (i--) {
if (arr1[i] !== arr2[i]) {
return false;
}
}
return true;
}
function indexOf(arr, val, comparer) {
for (var i = 0, len = arr.length; i < len; ++i) {
if ( i in arr && comparer(arr[i], val) ) {
return i;
}
}
return -1;
}
var tw = [[3, 0], [11, 0], [3, 14], [11, 14]];
alert( indexOf(tw, [3, 0], arraysIdentical) ); // Alerts 0
Upvotes: 14
Reputation: 25332
Because you're comparing two difference instance of array. Comparing objects returns true
only if they're the same instance, it doesn't matter if they contain the same data.
In your case, you could use this approach:
var tw = [[3, 0], [11, 0], [3, 14], [11, 14]];
if (~tw.join(";").split(";").indexOf(String([3, 0]))) {
// ...
}
Or something more ortodox like:
if (tw.filter(function(v) { return String(v) === String([3, 10]) })[0]) {
// ...
}
Where the condition can be adjusted depends by the content of the arrays.
Upvotes: 2
Reputation: 17960
This is because $.inArray
and indexOf
both use a shallow comparison using ===
.
Since the array you're passing is to indexOf
not the exact same in memory as the one in your 2D array, ===
returns false. You'll need to do a deep comparison to find the array properly - from a quick glance at the jQuery docs, this is not available there.
Upvotes: 0
Reputation: 5424
Arrays are objects. [3, 0] does not equal [3, 0] as they are different objects. That is why your inArray fails.
Upvotes: 2