简体   繁体   中英

javascript - How to check for existence of object in array

How can I check for the existence of an object in an array in javascript?

Here is a simple example. Let's say I have an array that looks like this:

let array = [{"zone": "WV", "zip": "56855"}, 
  {"zone": "SC", "zip": "28031"}, 
  {"zone": "TN", "zip": "84755"}]

And now I want to add an object to my array but only if it doesn't already exist.

For example attempting to add this object would fail:

let addMe = [{"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}]

But this would succeed

[{"zone": "SC", "zip": "55555"}, {"zone": "TN", "zip": "88888"}]

Obviously addMe is an array that would need to be stepped thru, failing on some objects, succeeding on others.

I am trying to use filter but its not working like I want. And I'm having to step thru the original array as well as step thru the object I'm trying to add, creating nested for loops which is confusing as hell. This is my attempt:

array.filter(function(item){
  addMe.forEach(function(element){
    if(item.zone != element.zone && zone.zip!= element.zip){
      array.push(element);
    }
  });
});

Is there a better way?

An alternative could be the function some to capture at least one object where not every value are equal.

 let array = [{"zone": "WV", "zip": "56855"}, {"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}], addMe = [{"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}]; addMe.forEach(o => { if (!array.some(a => Object.keys(a).every(k => a[k] === o[k]))) array.push(o); }); console.log(array); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

By using underscore.js . You may try something like this:

 let array = [ {"zone": "WV", "zip": "56855"}, {"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"} ]; let addMe1 = [{"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}]; let addMe2 = [{"zone": "SC", "zip": "55555"}, {"zone": "TN", "zip": "88888"}]; // This will fail. addMe1.forEach( item => !_.findWhere(array, item) ? array.push(item) : null); // This will success. addMe2.forEach( item => !_.findWhere(array, item) ? array.push(item) : null); console.log(array); 
 <script src="https://fastcdn.org/Underscore.js/1.8.3/underscore-min.js"></script> 

Alternatively you can compare all values of two objects with JSON.stringify.

So we first filter to not have any duplicate, by using some within which we compare the stringified objects.

let array = [{"zone": "WV", "zip": "56855"}, 
  {"zone": "SC", "zip": "28031"}, 
  {"zone": "TN", "zip": "84755"}]

const newObj = [{"zone": "WV", "zip": "55444"}, 
  {"zone": "SC", "zip": "28031"}]

array = array.concat(newObj.filter(x => !array.some(y => JSON.stringify(y) === JSON.stringify(x))))

console.log(array)

You can use native javascript, find() method in ECMAScript 6:

  let array = [{"zone": "WV", "zip": "56855"}, {"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}],
  addMe = [{"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}];

  addMe.forEach(place => {
    if (array.find((element) => element.zone == place.zone) === undefined) {
      array.push(place);
    }
  });

Apart right answers already given, there's a mistake in your if statement (item.zip instead of zone.zip) and a misunderstanding of the filter method (return true to keep and false to leave). So, if sticking on filter :

let valids = addMe.filter(function(element) {
  for(let i=0; i < array.length; i++) {
     if(item.zone === element.zone && item.zip === element.zip) return false // throw the item
  }
  return true; // keep the item
});

array.push(valids);

And a shorter way with findIndex for modern browser without filter :

for(let i = 0; i < addMe.length; i++) {
   let index = array.findIndex(item => item.zone === element.zone && item.zip === element.zip);
   // will return index of the matching item or -1

   if(index < 0) array.push(element); // Add it and you're done

   // or better to avoid array search inflation on already added elements
   // It will remove element from addMe
   addMe.splice(i,1);
}
// In case use of splice
array.push(addMe);

some method is also a good approach of working on array instead of addMe.

There are quick-to-develop, slow-to-run fixes, which involve searching through all the keys of all the objects every time. Or there's a slow-to-develop, quick-to-run solutions that build some sort of lookup so you don't have all the looping lookups. Here's a simple idea (more of a start of an idea) of the later.

Make a class (or object) that keeps a set of all known key/value pairs. This just concats them with a separator character (that shouldn't appear in the data). Now before adding, just do the constant-time lookup in the Set to check :

 let array = [ {"zone": "WV", "zip": "56855"}, {"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"} ] class unqiueCollection { constructor(arr, sep = "_"){ this.arr = [] this.sep = sep this.unique_keys = new Set arr.forEach((item) => this.add(item)) } add(item) { let key = item.zip + '_' + item.zone if (!this.unique_keys.has(key)) { this.unique_keys.add(key) this.arr.push(item) } else { console.log("already in array") } } } let coll = new unqiueCollection(array) // won't add coll.add({"zone": "SC", "zip": "28031"}) coll.add({"zip": "28031", "zone": "SC"}) // will add coll.add({"zone": "AK", "zip": "99577"}) console.log(coll.arr) 

This assumes all objects will just consists of zip and zone. If your items are more complex, of course the key and logic to make the keys will need to be more complex to decide what constitutes unique.

You could do this

    if(myArray !== undefined && myArray.length != 0) { 
     //your code here 
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM