midstack
midstack

Reputation: 2123

How can I check object equality in object array with using array includes function?

I want to check an array has the object which given as parameter to js includes function. For example:

let arr = [
    {'name': 'max', 'age': '20'},
    {'name': 'max', 'age': '21'},
    {'name': 'jane', 'age': '22'}];
console.log(arr.includes({'name': 'max', 'age': '21'})); // FALSE

That give me "false" value. How can I check object equality in object array without for loop eq.

Upvotes: 2

Views: 104

Answers (4)

georg
georg

Reputation: 214959

You can write a generic function like

let matches = flt => x => Object.keys(flt).every(k => flt[k] === x[k]);

and then

arr.some(matches({'name': 'max', 'age': '21'}))

This performs shallow, partial comparison. If you need other modes, like full and/or deep comparison, this would be far more tricky to implement. I'd suggest using lodash (_.isMatching, _.isEqual) in this case.

Upvotes: 3

natz
natz

Reputation: 731

Here's another way to achieve the same result :

If the structure of the object is not known well in before, i.e when they change dynamically, from an API or something then you can use the following solution

let arr = [
    {'name': 'max', 'age': '20'},
    {'name': 'max', 'age': '21'},
    {'name': 'jane', 'age': '22'}
];


let x =   {'name': 'max', 'age': '20'};
let result =arr.map( ele => JSON.stringify(ele)).includes(JSON.stringify(x));
console.log(result)

The above solution will work for nested objects as well.

Note The solution has two caveats

  1. It works provided that order of your keys remain constant throughout the array as well in the x object, the one which you wish to compare
  2. If there is too much of nesting in your objects then it will be really slow. I won't recommend JSON.stringify for anyone who care about performance.

Edit 1

  1. Doesn't work with Circular structures

Upvotes: 2

briosheje
briosheje

Reputation: 7446

Here is an option relying on both .some and .entries to ensure that all the key-value pairs passed exists and are matched inside the targeted array. This also will ignore the order of the keys, and accepts a dynamic input.

This example assumes that if fewer keys are provided, only these are checked. For example, checking for {'name': 'max'} only will return true.

let arr = [
    {'name': 'max', 'age': '20'},
    {'name': 'max', 'age': '21'},
    {'name': 'jane', 'age': '22'}];

function includedInArray(lookups, _arr) {
  // Ensure every lookup match.
  return _arr.some(i => {
    // Loop key-value pairs.
    return Object.entries(lookups).every(([key, value]) => {
      return i[key] === value;
    });
  });
};

console.log(includedInArray({
  'name': 'max',
  'age': '21'
 }, arr)); // should return true.
 
 console.log(includedInArray({
  'age': '21',
  'name': 'max'
 }, arr)); // should return true.
 
 console.log(includedInArray({
  'age': '55',
  'name': 'max'
 }, arr)); // should return false.
 
 console.log(includedInArray({
  'name': 'max'
 }, arr)); // should return true.

Upvotes: 2

sjahan
sjahan

Reputation: 5950

You cannot do this with includes because you don't handle the equality check and the objects are different, therefore, nothing matches.

To do what you want, you can use some or find !

let arr = [
    {'name': 'max', 'age': '20'},
    {'name': 'max', 'age': '21'},
    {'name': 'jane', 'age': '22'}
];

console.log(arr.some(({name, age}) => name === 'max' && age === '21'));
console.log(!!arr.find(({name, age}) => name === 'max' && age === '21'));

Please note that find returns the object, I've added !! to print a boolean result, but that's not necessarily mandatory.

Upvotes: 3

Related Questions