1

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();

8
  • You're right it has something to do with object equality because [] == [] is false. Commented Feb 20, 2017 at 21:45
  • I had an answer for this question, in this case could be util comparing arrays as string, jsfiddle.net/dbpLenwu Commented Feb 20, 2017 at 21:55
  • @trincot I don't believe this is a duplicate question as I was looking for the best way to find the index of the array and also wanted some background information on why indexOf didn't work (which wasn't the main discussion point). Many thanks. Commented Feb 20, 2017 at 21:56
  • see my jsfiddle above maybe could be useful in your case @poolts Commented Feb 20, 2017 at 21:58
  • 1
    @trincot Still think it's more associated than duplicated, but close it if you still think otherwise. Commented Feb 20, 2017 at 22:04

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @TJCrowder I owe you a beer :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.