ToddT
ToddT

Reputation: 3258

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?

Upvotes: 1

Views: 126

Answers (7)

aquiseb
aquiseb

Reputation: 1009

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)

Upvotes: 1

Parn
Parn

Reputation: 918

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>

Upvotes: 1

Mark
Mark

Reputation: 92461

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.

Upvotes: 0

Bertrand
Bertrand

Reputation: 1976

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.

Upvotes: 0

mwdev
mwdev

Reputation: 479

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);
    }
  });

Upvotes: 0

Aiden Kaiser
Aiden Kaiser

Reputation: 169

You could do this

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

Upvotes: -1

Ele
Ele

Reputation: 33736

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; }

Upvotes: 2

Related Questions