Reputation: 23
What's the best way to find the index of an array in a collection of arrays? Why doesn't indexOf() return the correct index? I'm guessing it's something to do with object equality?
I've seen other solutions loop through the collection and return the index reached when the equality check is met, but I'm still curious as to why indexOf() doesn't do the same thing. Additionally I can't use ES6's find / findIndex due to IE 11 support (as always). I've included my test code below. Many thanks.
var numbers = [ [1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12] ];
function getIndex (numbersToTest) {
return numbers.indexOf(numbersToTest);
};
function test() {
console.log( getIndex( [1, 2, 3, 4, 5, 6] ) ); // Except 0
console.log( getIndex( [7, 8, 9, 10, 11, 12] ) ); // Expect 1
console.log( getIndex( [2, 1, 3, 4, 5, 6] ) ); // Expect -1 (not in same order)
}
test();
Upvotes: 1
Views: 749
Reputation: 413737
Object references (including array references) are compared as reference values; one object reference is equal to another only if both references are to the exact same object. Comparison is not performed based on the content of the arrays, in your case. Even though those arrays you pass in have the same values, they're distinct arrays, and so are not equal to any of the arrays in the original list.
Instead, you need to use something like Array#find
(to find the entry) or Array#findIndex
(to find the entry's index), passing in a callback that compares the array in numbers
with numbersToTest
to see if they're equivalent arrays. This question's answers talk about various ways to efficiently compare arrays for equivalence.
For example:
var numbers = [ [1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12] ];
function getIndex (numbersToTest) {
return numbers.findIndex(function(entry) {
// Simple comparison that works for an array of numbers
return entry.length === numbersToTest.length && entry.every(function(number, index) {
return numbersToTest[index] === number;
});
});
};
function test() {
console.log( getIndex( [1, 2, 3, 4, 5, 6] ) ); // Expect 0
console.log( getIndex( [7, 8, 9, 10, 11, 12] ) ); // Expect 1
console.log( getIndex( [2, 1, 3, 4, 5, 6] ) ); // Expect -1 (not in same order)
}
test();
Note that both Array#find
and Array#findIndex
are newish (ES2015, aka "ES6"), but can be polyfilled for older JavaScript engines.
Upvotes: 1