22

I'm trying to compare two objects with underscore.

Object 1 (Filter)

{
  "tuxedoorsuit":"tuxedoorsuit-tuxedo",
  "occasions":"occasions-wedding"
}

Object 2 (Properties)

{
  "tuxedoorsuit":"tuxedoorsuit-tuxedo",
  "occasions":"occasions-wedding",
  "occasions":"occasions-prom",
  "product_fit":"product_fit-slim",
  "colorfamily":"colorfamily-black"
}

I want to return true when all items of Object 1 are found within Object 2. What would be the best underscore method to use for this?

5
  • 7
    What about underscorejs.org/#isEqual and underscorejs.org/#isMatch ? Commented Feb 20, 2015 at 15:26
  • 1
    @ArnaldoIgnacioGasparVéjar: You should make that an answer. It's much better than the currently accepted. Commented Feb 20, 2015 at 16:30
  • @Bergi : I agree isMatch would be far better. But actually it's interesting to note that it won't work in this case, because "Object 2" is malformed. It has two times the same property occasions. isMatch casts "Object 2" to a standard Object and this will only keep the last value of this property : occasions-prom. It will then return false. Commented Feb 20, 2015 at 16:55
  • @ArnaldoIgnacioGasparVéjar Ah, nice :) I included isMatch in my answer. Thanks :) Commented Feb 21, 2015 at 4:40
  • @slaur4: In fact, that the object syntax is malformed causes the parser to drop the "first" value (or, in strict mode, to throw a syntax error). isMatch is not to blame here, any other method would work the same - except when it would take object 2 as JSON and used a tolerant parser internally. Commented Feb 21, 2015 at 12:07

3 Answers 3

36

Edit: As per Arnaldo's comment, you can use isMatch function, like this

console.log(_.isMatch(object2, object1));

The description says,

_.isMatch(object, properties)

Tells you if the keys and values in properties are contained in object.

If you want to iterate yourself, just use _.keys and _.every, like this

_.every(_.keys(object1), function(currentKey) {
    return _.has(object2, currentKey) &&
        _.isEqual(object1[currentKey], object2[currentKey]);
});

Or the chained version,

var result = _.chain(object1)
    .keys()
    .every(function(currentKey) {
        return _.has(object2, currentKey) &&
            _.isEqual(object1[currentKey], object2[currentKey]);
    })
    .value();

If the result is true, it means that all the keys in object1 are in object2 and their values are also equal.

This basically iterates through all the keys of object1 and checks if the value corresponding to the key in object1 is equal to the value in object2.

Sign up to request clarification or add additional context in comments.

How would I use this inside _.filter?
@Casey Please edit the question and include all the information
This worked great! I was able to modify it a bit to work inside _.filter(). Thanks!
Actually, it looks like if the first item of object1 is found, then it won't check the second item.
@Casey JavaScript objects are HashMap implementations. So, if there are two items which are mapped to the same Hash value, then either of them will be overwritten by the other one.
12

To Compare two objects using underscore.js

 **isEqual :** _.isEqual(object, other) 

Performs an optimized deep comparison between the two objects, to determine if they should be considered equal.

Ex :

var stooge = {name: 'moe', luckyNumbers: [13, 27, 34]};
    var clone  = {name: 'moe', luckyNumbers: [13, 27, 34]};
     _.isEqual(stooge, clone)  
      Returns True

While isEqual is quite useful, it won't work if the other object has an additional property, like in OP's case.
It will also not work if the order of keys is not identical :/
@zero_cool order of keys shouldn't matter. JSON only orders arrays, not hashes.
1

Based on previous function created simple consoling out function:

var compareMe = function (obj1, obj2, parentKey) {
  parentKey = parentKey || '';
  _.each(_.keys(obj1), function (key) {
    if(_.isObject(obj1[key]) ) {
        compareMe(obj1[key], obj2[key], parentKey + key + '.')
    } else {
        if (!_.has(obj2, key) || !_.isEqual(obj1[key], obj2[key])) {
            console.log(parentKey + key, obj1[key], obj2[key]);
        }
    }
  })
};

And call like: compareMe(obj1, obj1)

Comments

Your Answer

Draft saved
Draft discarded

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.