_.intersection([], [])
仅适用于原始类型,对吗?
它不适用于对象。如何使它与对象一起工作(可能通过检查“Id”字段)?
var a = [ {'id': 1, 'name': 'jake' }, {'id':4, 'name': 'jenny'} ]
var b = [ {'id': 1, 'name': 'jake' }, {'id': 9, 'name': 'nick'} ]
在此示例中,结果应为:
_.intersection(a, b);
[{'id':1,'name':'jake'}];
答案 0 :(得分:24)
您可以根据下划线的功能创建另一个功能。您只需要从原始函数更改一行代码:
_.intersectionObjects = 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); });
});
});
};
在这种情况下,您现在使用下划线的isEqual()方法而不是JavaScript的相等比较器。我用你的例子尝试了它并且它有效。以下是有关isEqual函数的下划线文档的摘录:
_.isEqual(object, other)
Performs an optimized deep comparison between the two objects, to determine if they should be considered equal.
您可以在此处找到文档:http://documentcloud.github.com/underscore/#isEqual
我在jsFiddle上放了代码,这样你就可以测试并确认它:http://jsfiddle.net/luisperezphd/jrJxT/
答案 1 :(得分:23)
这是一种应该灵活且性能更好的替代算法。其中一项改进是您可以指定自己的比较函数,因此在您的情况下,如果它是唯一标识符,您只需比较id。
function intersectionObjects2(a, b, areEqualFunction) {
var results = [];
for(var i = 0; i < a.length; i++) {
var aElement = a[i];
var existsInB = _.any(b, function(bElement) { return areEqualFunction(bElement, aElement); });
if(existsInB) {
results.push(aElement);
}
}
return results;
}
function intersectionObjects() {
var results = arguments[0];
var lastArgument = arguments[arguments.length - 1];
var arrayCount = arguments.length;
var areEqualFunction = _.isEqual;
if(typeof lastArgument === "function") {
areEqualFunction = lastArgument;
arrayCount--;
}
for(var i = 1; i < arrayCount ; i++) {
var array = arguments[i];
results = intersectionObjects2(results, array, areEqualFunction);
if(results.length === 0) break;
}
return results;
}
你可以像这样使用它:
var a = [ { id: 1, name: 'jake' }, { id: 4, name: 'jenny'} ];
var b = [ { id: 1, name: 'jake' }, { id: 9, name: 'nick'} ];
var c = [ { id: 1, name: 'jake' }, { id: 4, name: 'jenny'}, { id: 9, name: 'nick'} ];
var result = intersectionObjects(a, b, c, function(item1, item2) {
return item1.id === item2.id;
});
或者您可以省略该功能,它将使用下划线_.isEqual()函数,如下所示:
var result = intersectionObjects(a, b, c);
你可以在jsFiddle上找到它:http://jsfiddle.net/luisperezphd/43vksdn6/
答案 2 :(得分:5)
下划线中的数组方法非常强大,您只需要几行就可以完成您想要的操作:
var a = [ {'id': 1, 'name': 'jake' }, {'id':4, 'name': 'jenny'} ];
var b = [ {'id': 1, 'name': 'jake' }, {'id': 9, 'name': 'nick'} ];
var result = _(a).chain().map(function(ea) {
return _.find(b, function(eb) {return ea.id == eb.id;});
}).compact().value();
如果你有大型数组,你可以通过一个额外的行去除compact()
调用:
var result = [];
_.each(a, function(ea) {
var entry = _.find(b, function(eb) {return ea.id == eb.id;});
if (entry) result.push(entry);
});
答案 3 :(得分:4)
我想为这些案例分享我的一般解决方案。
我使用mixin添加了一个通用函数来强调,它根据给定的Hash函数对两个集合执行二进制“数组”操作:
_.mixin({
collectionOperation: function(arr1, arr2, hash, action) {
var iArr1 = _(arr1).indexBy(hash)
, iArr2 = _(arr2).indexBy(hash);
return action(_(iArr1).keys(), _(iArr2).keys()).map(function (id) {
return iArr1[id] || iArr2[id];
});
}
});
用法示例:
_([{id:1,v:'q'},{id:2,v:'p'}]).collectionOperation([{id:3,v:'pq'}], 'id', _.union )
请注意,'id'可以替换为函数。
我相信这个解决方案是O(n + m)。
答案 4 :(得分:3)
从技术上讲,它确实可以处理对象,但是你需要注意引用相等性。
var jake = {'id': 1, 'name': 'jake' },
jenny = {'id':4, 'name': 'jenny'},
nick = {'id': 9, 'name': 'nick'};
var a = [jake, jenny]
var b = [jake, nick];
_.intersection(a, b);
// is
[jake]
答案 5 :(得分:3)
在lodash 4.0.0中。我们可以这样试试
var a = [ {'id': 1, 'name': 'jake' }, {'id':4, 'name': 'jenny'} ];
var b = [ {'id': 1, 'name': 'jake' }, {'id': 9, 'name': 'nick'} ];
_.intersectionBy(a, b, 'id');
输出:
[{&#39; id&#39;:1,&#39; name&#39;:&#39; jake&#39; }];
答案 6 :(得分:2)
var a = [ {'id': 1, 'name': 'jake' }, {'id':4, 'name': 'jenny'} ];
var b = [ {'id': 1, 'name': 'jake' }, {'id': 9, 'name': 'nick'} ];
工作职能:
function intersection(a,b){
var c=[];
for(m in a){
for(n in b){
if((a[m].id==a[n].id)&&(a[m].name==b[n].name))
c.push(a[m]);
}}
return c;
}
console.log(intersection(a,b));
在Pointy的建议之后我也尝试过jQuery中的代码。比较必须根据JSON对象的结构进行自定义。
<script type="text/javascript">
jQuery(document).ready(function(){
var a = [ {'id': 1, 'name': 'jake' }, {'id':4, 'name': 'jenny'} ];
var b = [ {'id': 1, 'name': 'jake' }, {'id': 9, 'name': 'nick'} ];
var c=[];
jQuery.each(a, function(ka,va) {
jQuery.each(b, function(kb,vb) {
if(compare(va,vb))
c.push(va);
});
});
console.log(c);
});
function compare(a,b){
if(a.id==b.id&&a.name==b.name)
return true;
else return false;
}
</script>
答案 7 :(得分:0)
如果您只想比较对象:
b = {"1":{"prod":"fibaro"},"2":{"prod":"aeotec"},"3":{"prod":"sw"}};
a = {"1":{"prod":"fibaro"}};
_.intersectObjects = function(a,b){
var m = Object.keys(a).length;
var n = Object.keys(b).length;
var output;
if (m > n) output = _.clone(a); else output = _.clone(b);
var keys = _.xor(_.keys(a),_.keys(b));
for(k in keys){
console.log(k);
delete output[keys[k]];
}
return output;
}
_.intersectObjects(a,b); // this returns { '1': { prod: 'fibaro' } }
答案 8 :(得分:0)
//nested array is in the format of [[],[],[]]
function objectArrayIntersection(nestedArrays){
let intersectingItems = [];
let uniqArr = _.uniq(_.flatten(nestedArrays)); //intersecting items removed
const countOfNestedArrays = nestedArrays.length;
for (let index = 0; index < uniqArr.length; index++) {
let uniqItem = uniqArr[index];
let foundCount = 0;
for(var j = 0;j<countOfNestedArrays;j++){
var i = _.indexOf(nestedArrays[j],uniqItem);
if(i != -1)
foundCount ++;
}
if(foundCount == countOfNestedArrays){
intersectingItems.push(uniqItem);
}
}
return intersectingItems;
}
我试图用这种方式解决它。
答案 9 :(得分:-2)
var a = {a:'a1',b:'b1'},
b = {a:'a2',b:'b2',c:'c2'};
_.pick(a,_.intersection(_.keys(a),_.keys(b)));
// {a:'a1',b:'b1'}