1

I have an array of objects, and I need to prevent duplicate objects of being added to the array. I've tried the following code to check for duplicates:

const array = [{ name: 'John' }];

const newName = {
  name: 'John'
};
console.log(array);
console.log(newName);

if (array.includes(newName)) {
  console.log(newName.name + ' exists');
} else {
  console.log('name does not exist');
}

Console logging tells that the object NewName is exactly the same as array[0]. However,

if(array.includes(newName))

returns false.

What I'm I doing wrong? I tried the solutions in this post as well with no luck:

How do I check if an array includes an object in JavaScript?

tekos
  • 67
  • 4
  • Possible duplicate of [Comparing Arrays of Objects in JavaScript](https://stackoverflow.com/questions/27030/comparing-arrays-of-objects-in-javascript) – Mebin Joe Mar 20 '19 at 07:15
  • Possible duplicate of [How to determine if Javascript array contains an object with an attribute that equals a given value?](https://stackoverflow.com/questions/8217419/how-to-determine-if-javascript-array-contains-an-object-with-an-attribute-that-e) and [Typescript : Check if object exist in array by value](https://stackoverflow.com/questions/51498419) – adiga Mar 20 '19 at 07:37

7 Answers7

4

Simply, you can use array.some from Array.prototype.some() documentation.

In your own example, you can do some tweaks to your program:

const array = [{ name: "John" }];

  const newName = {
    name: "John"
  };
  console.log(array);
  console.log(newName);

  if (array.some(object => object.name === newName.name)) {
    console.log(newName.name + " exists");
  } else {
    console.log("name does not exist");
  }
3

If the name is the identity of the object, you can use some function on array:

const array = [{ name: 'John' }];    
const newName = { name: 'John' };

if (array.some(({name}) => name === newName.name)) {
  console.log(newName.name + ' exists');
} else {
  console.log('name does not exist');
}

Or you can check if the count of properties is the same and then every property with:

const array = [{ name: 'John', age: 33 }, { name: 'John', age: 45 }];    
const newName = { age: 33, name: 'John' };

if (array.some(x => Object.keys(x).length === Object.keys(newName).length && Object.keys(x).every(p => x[p] === newName[p]))) {
  console.log(newName.name + ' exists');
} else {
  console.log('name does not exist');
}
ttulka
  • 10,309
  • 7
  • 41
  • 52
3

The thing you're missing is that includes checks for identity when you use it on an object. newName has the same properties as the object in your array, but it isn't the same object any more than two people named John are the same person. For a more obvious example, run {} == {} and you'll get false.

To check if the array contains an object with the same name, you can use some and pass it a function to compare the object, e.g.

array.some(e => e.name == newName.name)
John Montgomery
  • 6,739
  • 9
  • 52
  • 68
2

use it :

var newName = {
 name: 'John'
};
console.log(array);
console.log(newName.name);
var found = array.some(obj => obj.name === newName.name);

if (found) {
 console.log(newName.name + ' exists');
} else {
 console.log('name does not exist');
}
Shiva Kumar N
  • 371
  • 3
  • 11
1

const array = [{
  name: 'John'
}];

const newName = {
  name: 'John'
};

let resultArr = array.filter((item) => {
  return item.name === newName.name
})

let elementPresentMsg;

if (resultArr.length > 0) {
  elementPresentMsg = newName.name + ' exists';
} else {
  elementPresentMsg = 'name does not exist'
}

document.getElementById('msg').innerHTML = elementPresentMsg;
<html>

<body>

  <p id="msg"></p>

</body>

</html>

If you want to find the name or any other value from array, if attributes of object are same as that in array of objects, the following should be helpful:

const array = [{ name: 'John' }];

const newName = {
  name: 'John'
};

let resultArr = array.filter((item) => {
    return item.name === newName.name
})

if (resultArr.length > 0) {
  alert(newName.name + ' exists'); //any way to print result instead of alert
} else {
  alert('name does not exist'); //any way to print result instead of alert
}
Prathmesh Kadam
  • 186
  • 2
  • 10
0

This is because you are trying to compare two different instances of objects which will never be equal.

But if you convert the objects to primitive strings by doing JSON.stringify you can then use Array.includes for deep comparison. As ttulka pointed out, this will only work if the object to be searched has the properties in the same order as the object to find in the array.

const array = [{ name: 'John', age: 33 }];
const newName = {
  name: 'John',
  age: 33
};
if (array.map(obj => JSON.stringify(obj)).includes(JSON.stringify(newName))) {
  console.log(newName.name + ' exists');
} else {
  console.log('name does not exist');
}

If you look into the Array#includes polyfill in MDN, you would see that the comparison happens using the === strict equality operator:

function sameValueZero(x, y) {
   return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
}

// 7. Repeat, while k < len
while (k < len) {
  // a. Let elementK be the result of ? Get(O, ! ToString(k)).
  // b. If SameValueZero(valueToFind, elementK) is true, return true.
  if (sameValueZero(o[k], valueToFind)) {
      return true;
  }
  // c. Increase k by 1. 
  k++;
}

So when you compare two different object literals using === they won't be equal:

console.log({name :"John"} === {name :"John"});

But primitive strings on the other hand are equal if you compare them with ===:

console.log('{name:"John"}' === '{name:"John"}');

But the same is not true for String objects:

console.log(new String('{name:"John"}') === new String('{name:"John"}'));
Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44
  • `JSON.stringify` doesn't work for `const array = [{ name: 'John', age: 33 }]; const newName = { age: 33, name: 'John'};` even the objects are actually same. – ttulka Mar 20 '19 at 07:35
  • 1
    No, you didn't ... change the order of properties... `JSON.stringify({ age: 33, name: 'John' }) !== JSON.stringify({ name: 'John', age: 33 })` – ttulka Mar 20 '19 at 07:39
  • @ttulka yes if you change the order the, the output string from `JSON.stringify` is different so they won't be equal. – Fullstack Guy Mar 20 '19 at 07:41
  • 1
    @ttulka I will update this observation in my answer, Thanks for pointing this out! – Fullstack Guy Mar 20 '19 at 07:41
0

That is because array[0] not equal newName. In Javascript, they point to the different element. You can try console.log(array[0] == newName), and you will get false.
If you want to find the duplicates, you can try like this:

if (JSON.stringify(array).indexOf(JSON.stringify(newName)) != -1) {
  console.log('exist')
}
else {
  console.log('not exist')
}
Rouzip
  • 101
  • 3
  • This doesn't work generally because `JSON.stringify({ age: 33, name: 'John' }) !== JSON.stringify({ name: 'John', age: 33 })` – ttulka Mar 20 '19 at 07:41
  • @ttulka I thought the input order is fixed, this is my fault. – Rouzip Mar 21 '19 at 08:05