269

I need to determine if an object already exists in an array in javascript.

eg (dummycode):

var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};
carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);

now the "carBrands" array contains all instances. I'm now looking a fast solution to check if an instance of car1, car2, car3 or car4 is already in the carBrands array.

eg:

var contains = carBrands.Contains(car1); //<--- returns bool.

car1 and car4 contain the same data but are different instances they should be tested as not equal.

Do I have add something like a hash to the objects on creation? Or is there a faster way to do this in Javascript.

I am looking for the fastest solution here, if dirty, so it has to be ;) In my app it has to deal with around 10000 instances.

no jquery

asked Jan 3, 2011 at 18:16
4
  • Are you going to be checking based on dictionaries, or do you want to test using names? You could using a hash for carBrands, and then just testing on the keys you want. Commented Jan 3, 2011 at 18:23
  • 3
    you can use the method some: let contains = carsBrands.some( car => car.name == car1.name) Commented Oct 30, 2019 at 16:08
  • 8
    This question is different from the duplicate because it deals with objects rather than primitives. Using a simple === will only work in the simplest case where you have exact references to the objects in the array. Commented Aug 6, 2020 at 15:56
  • The caveats of using includes with objects have been addressed in How do I check if an array includes a value in JavaScript? multiple times. Some of the answers here don’t even consider this caveat. I don’t see a reason why this shouldn’t be closed as a duplicate. It does more harm than good to separate these questions by use case and leave the object reference caveat entirely unaddressed by one question, just because it doesn’t explicitly ask about object references. Commented Jan 29, 2023 at 11:25

18 Answers 18

196

Use something like this:

function containsObject(obj, list) {
 var i;
 for (i = 0; i < list.length; i++) {
 if (list[i] === obj) {
 return true;
 }
 }
 return false;
}

In this case, containsObject(car4, carBrands) is true. Remove the carBrands.push(car4); call and it will return false instead. If you later expand to using objects to store these other car objects instead of using arrays, you could use something like this instead:

function containsObject(obj, list) {
 var x;
 for (x in list) {
 if (list.hasOwnProperty(x) && list[x] === obj) {
 return true;
 }
 }
 return false;
}

This approach will work for arrays too, but when used on arrays it will be a tad slower than the first option.

answered Jan 3, 2011 at 18:26

8 Comments

+1. My answer was missing the point. This is the right one. (as a side note you can do exactly what the OP did extending Array.prototype)
Should add a var before the i or x, for example: for (var x in list)
it should be JSON.stringify(list[i]) === JSON.stringify(obj) and not list[i] === obj
@MartínNieva Probably because the object you're looking for isn't in the list, but rather a different object that compares as deeply-equal. In that case, using lodash's isEqual() would be preferable to abusing serialization. (In fact, using lodash, this whole solution becomes a one-liner, combining _.some and _.isEqual: _.some(list, v => _.isEqual(v, o)).)
can’t believe such a simple thing in Python could be such complex in js.
|
160

Why don't you use the indexOf method of javascript arrays?

Check this out: MDN indexOf Arrays

Simply do:

carBrands.indexOf(car1);

It will return you the index (position in the array) of car1. It will return -1 if car1 was not found in the array.

http://jsfiddle.net/Fraximus/r154cd9o

Edit: Note that in the question, the requirements are to check for the same object referenced in the array, and NOT a new object. Even if the new object is identical in content to the object in the array, it is still a different object. As mentioned in the comments, objects are passed by reference in JS and the same object can exist multiple times in multiple structures.
If you want to create a new object and check if the array contains objects identical to your new one, this answer won't work (Julien's fiddle below), if you want to check for that same object's existence in the array, then this answer will work. Check out the fiddles here and in the comments.

answered Jul 30, 2013 at 8:25

12 Comments

indexOf always return -1 when you try to find object in an array... Tiny example here : jsfiddle.net/7B7dQ/1
Why does this have 40 upvotes if it plainly doesn't work?
Gents, in the question, the OP wanted something like carBrands.Contains(car1). If you do carBrands.indexOf(car1), IT WORKS. Check this out: jsfiddle.net/Fraximus/r154cd9o
In Julien's fiddle, it won't work because it's a new object, even though they are identical.
Remember that objects in JS are passed by reference. This means that two objects that have the same properties with the same values are not the same object. It also means that an object can actually exist in multiple arrays simultaneously. Example: jsfiddle.net/7B7dQ/33
|
46

Having been recently bitten by the FP bug reading many wonderful accounts of how neatly the functional paradigm fits with Javascript

I replicate the code for completeness sake and suggest two ways this can be done functionally.

 var carBrands = [];
 var car1 = {name:'ford'};
 var car2 = {name:'lexus'};
 var car3 = {name:'maserati'};
 var car4 = {name:'ford'};
 var car5 = {name:'toyota'};
 carBrands.push(car1);
 carBrands.push(car2);
 carBrands.push(car3);
 carBrands.push(car4);
 // ES6 approach which uses the includes method (Chrome47+, Firefox43+)
 carBrands.includes(car1) // -> true
 carBrands.includes(car5) // -> false

If you need to support older browsers use the polyfill, it seems IE9+ and Edge do NOT support it. Located in polyfill section of MSDN page

Alternatively I would like to propose an updated answer to cdhowie

// ES2015 syntax
function containsObject(obj, list) {
 return list.some(function(elem) {
 return elem === obj
 })
}
// or ES6+ syntax with cool fat arrows
function containsObject(obj, list) {
 return list.some(elem => elem === obj)
}
answered May 27, 2016 at 14:31

3 Comments

When I add var car6 = {name:'ford'}; to your first solution and try carBrands.includes(car6), it returns false. Can you explain this?
@PrasanthGanesan the carBrands is an Array of objects, in this case with the shape of having a key of 'name' and a value of the type of car brand as a string. If you do not push your var car6 object into the array the include method will indeed return false, if you push it onto array it will return true. see my jsbin example - jsbin.com/xeluyizaze/edit?js,console
Same approach but actually comparing the objects: arr.some((e) => Object.entries(e).toString() === Object.entries(obj).toString())
21

try Array.prototype.some()

MDN Array.prototype.some


 function isBiggerThan10(element, index, array) {
 return element > 10;
 }
 [2, 5, 8, 1, 4].some(isBiggerThan10); // false
 [12, 5, 8, 1, 4].some(isBiggerThan10); // true
answered Jul 19, 2016 at 2:29

Comments

17

You could use jQuery's grep method:

$.grep(carBrands, function(obj) { return obj.name == "ford"; });

But as you specify no jQuery, you could just make a derivative of the function. From the source code:

function grepArray( elems, callback, inv ) { 
 var ret = []; 
 // Go through the array, only saving the items 
 // that pass the validator function 
 for ( var i = 0, length = elems.length; i < length; i++ ) { 
 if ( !inv !== !callback( elems[ i ], i ) ) { 
 ret.push( elems[ i ] ); 
 } 
 } 
 return ret; 
} 
grepArray(carBrands, function(obj) { return obj.name == "ford"; });
leszek.hanusz
5,3572 gold badges44 silver badges61 bronze badges
answered Jan 3, 2011 at 18:30

1 Comment

What is inv? Where is it used?
12

I used underscore javascript library to tweak this issue.

function containsObject(obj, list) {
 var res = _.find(list, function(val){ return _.isEqual(obj, val)});
 return (_.isObject(res))? true:false;
}

please refer to underscore.js documentation for the underscore functions used in the above example.

note: This is not a pure javascript solution. Shared for educational purposes.

answered Mar 11, 2013 at 7:11

Comments

9

You can just use the equality operator: ==. Objects are checked by reference by default, so you don't even need to use the === operator.

try this, just make sure you're using the correct variable reference in the place of car1:

var i, car, l = cars.length;
for (i = 0; i < l; i++)
{
 if ((car = cars[i]) == car1)
 {
 break;
 }
 else car = null;
}

Edit to add:

An array extension was mentioned, so here's the code for it:

Array.prototype.contains = Array.prototype.contains || function(obj)
{
 var i, l = this.length;
 for (i = 0; i < l; i++)
 {
 if (this[i] == obj) return true;
 }
 return false;
};

Note that I'm caching the length value, as the Array's length property is actually an accessor, which is marginally slower than an internal variable.

FabianCook
20.6k17 gold badges72 silver badges119 bronze badges
answered Jan 3, 2011 at 18:28

4 Comments

Since you brought it up. Faster to loop backwards with a while. var i = this.length; while (i--) { ... }; Since going backwards won't hurt here, may as well. ajaxian.com/archives/fast-loops-in-js
@Hemlock good point, except it'd have to be this[i-1] in the loop.
Nope, look again. i gets decremented after it gets tested.
"You can just use the equality operator: ==. Objects are checked by reference by default, so you don't even need to use the === operator." I would advise strongly against using the == operator anywhere. It isn't even transitive!
9

I would use a generic iterator of property/value over the array. No jQuery required.

arr = [{prop1: 'val1', prop2: 'val2'}, {prop1: 'val3', prop2: 'val4'}];
objectPropInArray(arr, 'prop1', 'val3'); // <-- returns true
function objectPropInArray(list, prop, val) {
 if (list.length > 0 ) {
 for (i in list) {
 if (list[i][prop] === val) {
 return true;
 }
 }
 }
 return false; 
}
sampathsris
22.4k12 gold badges74 silver badges102 bronze badges
answered Feb 28, 2015 at 5:15

Comments

6

try this , You can use the JavaScript some() method to find out if a JavaScript array contains an object.

<script>
// An array of objects
var persons = [{name: "Harry"}, {name: "Alice"}, {name: "Peter"}];
// Find if the array contains an object by comparing the property value
if(persons.some(person => person.name === "Peter")){
 alert("Object found inside the array.");
} else{
 alert("Object not found.");
}
</script>
answered Aug 14, 2022 at 12:06

1 Comment

Note that if try to find the object inside an array using the indexOf() method like persons.indexOf({name: "Harry"}) it will not work (always return -1). Because, two distinct objects are not equal even if they look the same
4

You could try sorting the array based on a property, like so:

carBrands = carBrands.sort(function(x,y){
 return (x == y) ? 0 : (x > y) ? 1 : -1;
});

Then you can use an iterative routine to check whether

carBrands[Math.floor(carBrands.length/2)] 
// change carBrands.length to a var that keeps 
// getting divided by 2 until result is the target 
// or no valid target exists

is greater or lesser than the target, and so on, which will let you go through the array quickly to find whether the object exists or not.

answered Jan 3, 2011 at 18:32

Comments

3

EDIT 05/18/2022

The most simple way using ES6:

const arrayContainsObject = <T extends Record<string, unknown>>(array: T[], object: T) => {
 return array.some(item => Object.keys(item).every(key => item[key] === object[key]))
}

Use like so:

const arr = [{
 prop1: 'value1',
 prop2: 'value2'
}]
const obj1 = {
 prop1: 'value1',
 prop2: 'value2'
}
const obj2 = {
 prop2: 'value2',
 prop1: 'value1'
}
const obj3 = {
 prop0: 'value0',
 prop1: 'value1'
}
arrayContainsObject(arr, obj1) // true
arrayContainsObject(arr, obj2) // true, even when props are arranged in different order
arrayContainsObject(arr, obj3) // false

Previous answer, don't use (because the order of props in an object needs to be identical)

const arr = [{
 prop: 'value'
}]
const obj = {
 prop: 'value'
}
arr.some((e) => Object.entries(e).toString() === Object.entries(obj).toString()) // true
answered Jan 12, 2022 at 10:17

Comments

2

You can convert both the JSON objects to string and simply check if the bigger json contains the smaller json.

console.log(JSON.stringify(carBrands).includes(JSON.stringify(car1))); // true
console.log(JSON.stringify(carBrands).includes(JSON.stringify(car5))); // false
answered Mar 25, 2022 at 3:04

Comments

1

i know this is an old post, but i wanted to provide a JQuery plugin version and my code.

// Find the first occurrence of object in list, Similar to $.grep, but stops searching 
function findFirst(a,b){
var i; for (i = 0; i < a.length; ++i) { if (b(a[i], i)) return a[i]; } return undefined;
}

usage:

var product = $.findFirst(arrProducts, function(p) { return p.id == 10 });
answered Oct 23, 2014 at 14:06

Comments

1

This function is to check for a unique field. Arg 1: the array with selected data Arg 2: key to check Arg 3: value that must be "validated"

function objectUnique( array, field, value )
{
 var unique = true;
 array.forEach(function ( entry )
 {
 if ( entry[field] == value )
 {
 unique = false;
 }
 });
 return unique;
}
answered Feb 25, 2016 at 8:39

Comments

1

you can use Array.find().

in your case is going to look like this

carBrands.find(function(car){
 let result = car.name === 'ford'
 if (result == null){
 return false;
 } else {
 return true
 }
});

if car is not null it will return the javaScript Object which contains the string 'ford'

about14sheep
2,0792 gold badges13 silver badges20 bronze badges
answered Jun 7, 2022 at 20:30

Comments

1

The issue with many of the answers here is that they will NOT find an object in an array that is equal to another object. They will only search for an EXISTING object that has a pointer to it in an array.

Quick fix using lodash to see if ANY equal object is in an array:

import _ from 'lodash';
_.find(carBrands, car1); //returns object if true, undefined if false

Working Plunker using this method: https://plnkr.co/edit/y2YX9o7zkQa2r7lJ

answered Nov 17, 2022 at 18:11

Comments

0

You could also a the findIndex

var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
carBrands.push(car1);
if (carBrands.findIndex(f => f.name === car1.name) === -1) { 
 console.log('not contain')
} else {
 console.log('contain')
}
if (carBrands.findIndex(f => f.name === car2.name) === -1) { 
 console.log('not contain')
} else {
 console.log('contain')
}

answered Sep 27, 2022 at 12:42

Comments

-1

if its possible to use es6

carBrands.filter(carBrand => carBrand.name === carX.name).length > 0

if it's true there is a similarity

answered Mar 15, 2022 at 14:18

1 Comment

-1. Unless you plan to do something with every item you find, please don't use filter to iterate through your entire list. Even if the item is found at position 0, filter will continue until all items are read. Use find or some instead, as they will stop looping as soon as a match is found.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.