简体   繁体   中英

How do I find the intersection of an array of arrays that contain objects using Javascript/underscorejs?

I can't figure out how to find the intersection of this set of arrays:

[
 [
  {"name":"product1","light":"1"},
  {"name":"product2","light":"2"},
  {"name":"product5","light":"5"},
  {"name":"product4","light":"4"}
 ],
 [
  {"name":"product2","light":"2"},
  {"name":"product3","light":"3"},
  {"name":"product4","light":"4"}
 ],[...more arrays with objects]
]

This is just sample data , the real set I have changes a lot but with that structure. I want the returned intersection to look like this (a single array of the intersected objects):

[
 {"name":"product2","light":"2"},
 {"name":"product4","light":"4"},
]

I tried this together with LoDashjs and Underscorejs:

_.intersectionObjects = _.intersect = function(array) {
var slice = Array.prototype.slice; // added this line as a utility
var rest = slice.call(arguments, 1);
return _.filter(_.uniq(array), function(item) {
  return _.every(rest, function(other) {
    //return _.indexOf(other, item) >= 0;
    return _.any(other, function(element) { return _.isEqual(element, item); });
  });
});
};

I need this because I am trying to create a tags system using knockoutjs. I have a layout of categorized tag buttons that write to a "filter" observable array on click, the only thing left is to find the intersection of the filtered products that are contained in this observable array.

Please help me out, I've been trying to solve this for two days straight but lack the javascript knowledge to figure it out. Thanks in advance!

try adding they apply method:

  var myArr = [
    [
      {"name":"product1","light":"1"},
      {"name":"product2","light":"2"},
      {"name":"product5","light":"5"},
      {"name":"product4","light":"4"}
    ],
    [
      {"name":"product2","light":"2"},
      {"name":"product3","light":"3"},
      {"name":"product4","light":"4"}
    ]
  ]

  _.intersectionObjects = _.intersect = function(array) {
    var slice = Array.prototype.slice;
    var rest = slice.call(arguments, 1);
    return _.filter(_.uniq(array), function(item) {
      return _.every(rest, function(other) {
        return _.any(other, function(element) {
          return _.isEqual(element, item);
        });
      });
    });
  };

  var myIntersection = _.intersectionObjects.apply(_, myArr);

  for (var i = 0; i < myIntersection.length; i++) {
    console.log(myIntersection[i]);
  }

  // Sample Output:
  // Object {name: "product2", light: "2"}
  // Object {name: "product4", light: "4"}

Here's a method I used that seems to work well.

 var arr1 = [{"id":"1"},{"id":"2"},{"id":"3"}]; var arr2 = [{"id":"1"},{"id":"3"}]; function match(item){ var isMatch = _.matcher(item); var matches = _.filter(arr2, isMatch); return matches[0]; } var matchArray = _.compact(_.map(arr1, function(val){ return match(val)})); document.write(JSON.stringify(matchArray)); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> 

You are likely to run across errors if you're comparing just the objects themselves, as this will return false:

var o1 = {"foo":"bar"};
var o2 = {"foo":"bar"};
return o1 == o2;

You'll need to compare the values inside of the objects, and intersect based on those:

The JSFiddle here does what you like. http://jsfiddle.net/turiyag/bWrQW/6/

function valueIntersect(a1, a2) {
    var aReturn = [];
    for(i1 in a1) {
        o1 = a1[i1];
        for (i2 in a2) {
            o2 = a2[i2];
            if(equals(o1,o2)) {
                aReturn.push(o1);
                break;
            }
        }
    }
    return aReturn;
}

function equals(o1, o2) {
    if (!o2 || o1.length != o2.length) {
        return false;
    }
    for (i in o1) {
        if (o1[i] !== o2[i]) {
            return false;
        }
    }
    return true;
};

根据https://lodash.com/docs#intersectionBy

_.intersectionBy([arrays], [iteratee=_.identity])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM