简体   繁体   English

如何使用Javascript / underscorejs找到包含对象的数组数组的交集?

[英]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: 我和LoDashjs以及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. 我需要这个,因为我正在尝试使用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. 请帮帮我,我一直试图连续两天解决这个问题,但缺乏javascript知识来解决这个问题。 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: 如果您只是比较对象本身,则可能会遇到错误,因为这将返回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. JSFiddle在这里做你喜欢的事。 http://jsfiddle.net/turiyag/bWrQW/6/ 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])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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