Backbone.js: compare model attributes in a collection

I have a collection of unlimited volume (maybe 0, maybe 1000, maybe a million). I need to look for the attributes of each model in the collection and return the attributes (and their values) that are the same.

For example, if I have three models in my collection:

modelOne:
  color: "red"
  age: 10
  size: "large"

modelTwo:
  color: "red"
  age: 11
  size: "medium"

modelThree:
  color: "red"
  age: 9
  size: "large"

I need an application to return color: "red"(or another derivation that can be parsed), since it is the only attribute equal to all three models.

Edit John Munsch's solution worked very well, but now the requirements have changed since some attributes can now be arrays. Is there a way to compare regular attributes and attributes that are arrays?

New code example:

modelOne:
  color: "red"
  age: 10
  sizes: ["small", "large"]

modelTwo:
  color: "red"
  age: 9
  sizes: ["small", "large"]
+3
1

jsFiddle : http://jsfiddle.net/JohnMunsch/3NMGD/

. jsFiddle , .

var model = [
    {
      color: "red",
      age: 10,
      size: [ "small", "large" ]
    },
    {
      color: "red",
      age: 11,
      size: [ "small", "large" ]
    },
    {
      color: "red",
      age: 9,
      size: [ "small", "large" ]
    }
];

function findCommonalities(data) {
    if (data.length > 0) {
        // It safe enough to get the list of keys from the very first
        // element. If the later ones differ, you know that the keys they
        // had but the first element didn't are guaranteed not to be in
        // the common set anyway because the first element didn't
        // have them.
        var keys = _.keys(data[0]);
        var commonalities = { };

        _.each(keys,
            function (key) {
                var values = _.pluck(data, key);

                if (values.length == data.length) {
                    // Sadly calling _.uniq() won't work when the values
                    // plucked out are arrays themselves. It calls ===
                    // and that not sufficient for arrays.
                    if (_.isArray(values[0])) {
                        // However, we can get a little tricky here.
                        // What if we _.zip() together all of the arrays
                        // (assuming the ordering for each array is the
                        // same) then we'll end up with an array of
                        // arrays where each one can again be tested
                        // with _.uniq() because each one will contain
                        // the same value taken from each array.
                        var zippedValues = _.zip(values);
                        console.log("zippedValues", zippedValues);

                        if (!_.find(zippedValues,
                            function (zippedValue) {
                                var uniqueValues = _.uniq(zippedValue);

                                // Note: This test is the inverse of the
                                // one below. We're trying to find any
                                // array that has more than one value in
                                // it. If we do then there some
                                // variance.
                                return uniqueValues.length != 1;
                            })) {
                            // We didn't find any arrays that had any
                            // variance so we want this as well.
                            commonalities[key] = values[0];
                        }
                    } else {
                        var uniqueValues = _.uniq(values);

                        if (uniqueValues.length == 1) {
                            commonalities[key] = uniqueValues[0];
                        }
                    }
                }
            }
        );

        return commonalities;
    } else {
        return { };
    }
}

console.log("commonalities: ", findCommonalities(model));

, .

+3

All Articles