Reputation: 1028
I need something like lodash.intersectionWith but I also need duplicated values in result array.
Example:
var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
_.intersectionWith(objects, others, _.isEqual);
Expected Result:
[{ 'x': 1, 'y': 2 },{ 'x': 1, 'y': 2 }]
Thanks in advance!
Upvotes: 4
Views: 6799
Reputation: 5963
You can find the intersection by filtering out items from the first array that don't match items in the second. Any duplicates in the first array will be kept.
var intersectwith = function(f,xs,ys){
return xs.filter(function(x){
return ys.some(function(y){
return f(x,y);
});
});
};
var equals = function(x,y){
return x === y;
};
console.log(intersectwith(equals, [1,2,3], [1,1,2,2,4]));
console.log(intersectwith(equals, [1,1,2,2,4], [1,2,3]));
Or, more readably, using ES6:
const intersectwith = (f,xs,ys) => xs.filter(x => ys.some(y => f(x,y)));
const equals = (x,y) => x === y;
console.log(intersectwith(equals, [1,2,3], [1,1,2,2,4]));
console.log(intersectwith(equals, [1,1,2,2,4], [1,2,3]));
Substitute _.isEqual
for equals
for comparing objects: jsfiddle.
Useful documentation:
Array.prototype.filter
Array.prototype.some
Upvotes: 3
Reputation: 30098
You can make use of differenceWith() to get the difference between the source object
and the symmetric difference of the source object
and the others
object using xorWith().
var result = _.differenceWith(
objects,
_.xorWith(objects, others, _.isEqual),
_.isEqual
);
var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
var intersection = _.intersectionWith(objects, others, _.isEqual);
var result = _.differenceWith(
objects,
_.xorWith(objects, others, _.isEqual),
_.isEqual
);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
Upvotes: 3
Reputation: 9819
Use reduce
to validate each object
in the first array
, then check if that object
exists in the second array
. If it exists, reduce
will push
that object
into its array
.
The reduce
function will return that new array
automagically.
var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
var res = objects.reduce(
function(arr, obj){
if(containsObject(obj, others))
arr.push(obj);
return arr;
},
[]
);
function containsObject(obj, list) {
var x;
var ret = false;
list.forEach(function(s){
ret = JSON.stringify(s) == JSON.stringify(obj);
});
return ret;
}
console.log(res);
Upvotes: 0