1

I'm making a Javascript application where I need to check an array of arrays (a nested array) for specific arrays containing two objects each. The nested array looks somewhat like this: [[obj1, obj2], [obj2, obj3], [obj3, obj1]]

The problem I have is that even though this part of the application doesn't raise any errors, it does not work as intended. I tried to approach it like this: array.includes([obj1, obj2]), but this returns false, even though the array does contain [obj1, obj2].

So why isn't this working the way it's intended, and what's a better approach for this situation?

Edit: I want to check with strict comparison of the objects included in the array, no matter the reference of the array containing them. How can I do that?

3
  • 3
    Because array.includes uses strict comparison === which compares array references. The literal you pass and the one in the array do not have the same reference. It does not compare by array content Commented Sep 8, 2019 at 17:35
  • 2
    Need to show us what those objects actually look like and what you want to search for. The toString() version of [object Object] is useless for debugging or developing against. See minimal reproducible example Commented Sep 8, 2019 at 17:35
  • Can you post the sample object stored in inner array and the comparison object? If the comparison object is exactly same as one in inner array you can filter on top array and condition can be JSON comparison of inner array and comparison array Commented Sep 8, 2019 at 17:36

3 Answers 3

2

In JS each array(object) is unique, even if it has the same content as another one:

console.log( {} == {} ); // false
console.log( [] == [] ); // false
console.log( [1, 2] == [1, 2] ); // false

So, you have to loop and compare each element one by one:

let arr = [
  [0, 0, 0], 
  [1, 1, 1],
  [2, 2, 2], 
]

console.log( arrInArr( arr, [3, 3, 3] ) ); // false
arr[3] = [3, 3, 3]; // new elem added
console.log( arrInArr( arr, [3, 3, 3] ) ); // true

function arrInArr(mama, child){
  for( let i = 0; i < mama.length; i++ ){
    // don't even starting to compare if length are not equal
    if( mama[i].length != child.length ){ continue }
    
    let match = 0; // To count each exact match
    for( let j = 0; j < child.length; j++ ){
      if( mama[i][j] === child[j] ){
        // We made sure, that they have equal length, and can use index 'j'
        // to compare each element of arrays. 
        match++;
      } else {
        break;
      }
    }
    if( match === child.length ){ // If each element exactly matched
      return true; 
    }
  }
  return false;
}

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

2 Comments

Code dumps are not useful answers.
Please don't post and then make the answer useful.
2

includes compares with ===, apparently your search array is only equivalent to one of the entries, not the same actual array.

You can use some with the callback checking whether every entry in the array being visited matches your search array.

const flag = arrayOfArrays.some(
    array => array.length === search.length && array.every(
        (entry, index) => entry === search[index]
   )
);

Note that this assumes the inner entries are comparable with ===. If not, substitute the appropriate way of comparing them.

Live Example:

function check(arrayOfArrays, search) {
    return arrayOfArrays.some(
        array => array.length === search.length && array.every(
            (entry, index) => entry === search[index]
       )
    );
}
console.log(
    "yes:", 
    check(
        [[1, 2], [3, 4], [5, 6], [7, 8]],
        [5, 6]
    )
);
console.log(
    "no:", 
    check(
        [[1, 2], [3, 4], [5, 6], [7, 8]],
        [6, 5] // Note the different order
    )
);

If you want to find the array in the array of arrays, you can use find instead of some. If you want to find its index in the array of arrays, you can use findIndex.

1 Comment

@georg - Doh! Thanks. Fixed.
0

If you use a package like lodash, it has a method for comparing if two objects are equal by content rather than by the much stricter === comparison: https://lodash.com/docs/4.17.15#isEqual

Using _.isEqual, you could then do something like this:

array.findIndex(item => _.isEqual(item, testObject)) >= 0

Lodash might even have a method to directly search an array with a deep-equals comparison too, but the above would get the job done.

2 Comments

There's no need to include an entire library for this basic functionality.
Lodash-es could be used, and then only the isEqual method imported. Plus sometimes it's better not to re-invent the wheel when a well-tested method already exists.

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.