2

I'm looking for a way to find any objects in one array that are not present in another array based upon that object's property. What's the best way to do this with jQuery or underscore?

Given the following example:

"array1":[
    {"testProperty":"A"}, 
    {"testProperty":"B"}, 
    {"testProperty":"C"}
]

"array2":[
    {"testProperty":"A", "User":"Smith"}, 
    {"testProperty":"B", "User":"Smith"}, 

]

I would want to return the third object from array1 whose testProperty is "C" since it's not present in array2.

I was able to find several examples of this issue here on stackoverflow, but not when needing to do so using properties from those objects.

5 Answers 5

3

I'm not sure if this counts, but if you can use lodash instead of underscore, there is a nice function called differenceBy:

var _ = require("lodash");

var array1 = [
  {"testProperty":"A"},
  {"testProperty":"B"},
  {"testProperty":"C"}
]

var array2 = [
  {"testProperty":"A", "User":"Smith"},
  {"testProperty":"B", "User":"Smith"}
]

var result = _.differenceBy(array1, array2, function(item) {
  return item["testProperty"]
});

console.log(result);
Sign up to request clarification or add additional context in comments.

Comments

2

A proposal in plain Javascript with a hash table for look-up.

var data = { "array1": [{ "testProperty": "A" }, { "testProperty": "B" }, { "testProperty": "C" }], "array2": [{ "testProperty": "A", "User": "Smith" }, { "testProperty": "B", "User": "Smith" }, ] },
    result = data.array1.filter(function (a) {
        return !this[a.testProperty];
    }, data.array2.reduce(function (r, a) {
        r[a.testProperty] = true;
        return r;
    }, Object.create(null)));

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

2 Comments

I prefer the jQuery approach but this works great, thanks!
@Haymak3r jQuery approach? what does that even mean? none of these answers require jQuery.
2

You can use filter with map

var a = {'array1': [{"testProperty":"A"}, {"testProperty":"B"}, {"testProperty":"C"}], 'array2': [{"testProperty":"A", "User":"Smith"}, {"testProperty":"B", "User":"Smith"}]};

var result = a.array1.filter(function(e) {
  return a.array2.map(el => { return el.testProperty}).indexOf(e.testProperty) == -1;
});

console.log(result);

1 Comment

This is incredibly inefficient. You map over all of array2 on each iteration of filter, which is totally unnecessary.
1

here's a version in plain es6 js using filter and some method:

array1 = [
    {"testProperty":"A"}, 
    {"testProperty":"B"}, 
    {"testProperty":"C"}
];

array2 =[
    {"testProperty":"A", "User":"Smith"}, 
    {"testProperty":"B", "User":"Smith"}, 

]
  
 var r = array1.filter(x =>
    ! Object.keys(x).some(z =>
      array2.some(w =>
      Object.keys(w).some(y => y === z && w[y] === x[z])
    )));
    
    document.write(JSON.stringify(r))

Comments

1

You could use underscore's reject and some to get what you want:

var result = _.reject(array1, item => _.some(array2, {testProperty: item.testProperty}));

If performance is a concern and testProperty is an unique key of the objects in array2 then you could create a hash using indexBy and check for the result using has:

var hash = _.indexBy(array2, 'testProperty');
var result = _.reject(array1, item => _.has(hash, item.testProperty));

1 Comment

thanks for sharing Gruff, it's great to see several different ways to implement the same functionality.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.