1

I want to compare an unlimited amount of objects in an array, like

{ a: true, b: false, c: "foo"}

and

{ a: false, b: false, c: "foo"}

and get a result like

[b,c]

This can be done with just two objects like this:

function compare(first, second) {
    var shared = []
    $.each(first, function(index, value){
        if(second[index] == value){
            shared.push(index)
        }
    })
    return shared
}

So my question is: How to write a (recursive) function that compares n objects and returns the properties they all have in common.

Thank you for reading this

6
  • btw i used jquery for the loop over objects ($.each) Commented Sep 24, 2015 at 17:49
  • 4
    I don't think it has to be recursive. Just use .reduce(). Commented Sep 24, 2015 at 17:50
  • 1
    So i could compare the first to the second one and then compare the result to the third and so on? Commented Sep 24, 2015 at 17:52
  • Right - From the first object you'd pick up all the properties/values, and then for each subsequent object you'd throw out the ones that don't match. At the end, you'd just collect up the property names as a final step. Commented Sep 24, 2015 at 17:54
  • 1
    You actually need .filter and .every Object.keys(first).filter(key => objects.every(obj => obj[key] === first[key]) ); Commented Sep 24, 2015 at 18:04

6 Answers 6

2

That's pretty simple if written literally:

function allCommonProperties(objects) {
    if (!objects.length) return [];
    var first = objects[0];
    return Object.keys(first).filter(function(p) {
        return objects.every(function(o) {
             return first[p] === o[p];
        });
    });
});

No need for recursion, no need for jQuery.

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

Comments

0

An alternative approach using .filter and .every. No libs.

Object.keys(first)
      .filter(function(key){
          return objects.every(function(obj){
             return obj[key] === first[key];
          });
      });

For ES6 envs

Object.keys(first).filter(key => objects.every(obj => obj[key] === first[key]));

Where

  • objects - an array of all objects to compare
  • first = objects.shift() - the first element

Comments

0

This solution features Array.prototype.filter in combination with Object.keys.

var setA = { a: true, b: false, c: "foo" },
    setB = { a: false, b: false, c: "foo" },
    commonProperties = Object.keys(setA).filter(function (k) {
        return setA[k] === setB[k];
    });

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

Comments

0

I'd do it with .reduce(), going through the array and accumulating an object containing only properties that have been found (with matching values) in all the objects so far.

I'll give my example with an "extend" function; if you're working with jQuery you could use $.extend() or you can write a simple one. The idea is to do a shallow copy of properties from one object into another, which'll be necessary for the first object in the list.

var objects = [ ... ]; // the array of objects
var resultObject = objects.reduce(function(result, obj) {
  if (result === null)
    result = extend({}, obj);
  else {
    Object.keys(result).forEach(function(key) {
      if (!(key in obj) || obj[key] !== result[key])
        delete result[key];
    });
  }
  return result;
}, null);
var resultProperties = Object.keys(resultObject);

Here's what extend() might look like:

function extend(obj) {
  var args = arguments;
  for (var i = 1; i < args.length; ++i)
    Object.keys(args[i]).forEach(function(key) {
      obj[key] = args[i][key];
    });
  return obj;
}

Comments

0

I think that work:

function compareObj(obj1,obj2){
    var ar =[];//you need an  array to put the diffirent property
    for(key in obj1){//getting all proo
        try{
            if (obj1[key]!=obj2[key]) //if there is diffirence 
                {
                    ar[ar.length-1]=key;
                    //key is the name of property 
                }
        }
        catch(err){
            console.log("Not the same type of objects");
            return false;
        }


    }
    return ar ;
}

Comments

0

This tries to iterate as least as possible. It mutates an array that holds the keys of the initial object every time a property is no longer found on the next object and will also stop iterating the rest of the array elements if there's no common properties left.

function filterByPropertyValue(arr) {
  var acc = {},
    initial, objectProperties;
  if (arr.length > 0) {
    initial = arr[1];
    objectProperties = Object.keys(initial);
    for (var i = 1; i < arr.length; i++) {
      if (objectProperties.length > 0) {
        objectProperties.forEach(function(prop, index) {
          if (initial[prop] === arr[i][prop]) {
            acc[prop] = initial[prop];
          } else {
            delete acc[prop];
            delete objectProperties[index];
          }
        });
      } else {
        break;
      }
    }
  }
  return acc;
}

var arr = [{ a: true, b: false, c: "foo"}, { a: false, b: false, c: "foo"}, { a: true, b: false, c: "bar"}];
document.getElementById('results').innerHTML = JSON.stringify(filterByPropertyValue(arr), null, '\t');
<pre id="results"></pre>

Comments

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.