Mikhail
Mikhail

Reputation: 1028

How can i get arrays intersection include duplicate values using Javascript

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

Answers (3)

1983
1983

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

ryeballar
ryeballar

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

Randy
Randy

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

Related Questions