4

I have to retrieve the values that exist only on Array B, but do not exist on Array A.

From my research, It is called:

relative complement of A in B

enter image description here

Values in the arrays may not be primitives.I need an efficient and functional apporach to this problem. I have found lodash _.without function, but it supports only array of primitive numbers.

Array A:

[{
    id: 1
},
{
    id:2
}]

Array B:

[{
    id:2
},
{
    id:3
}]

result should be:

[{
    id:3
}]

this object is the only one who exist on Array B, but not on Array A.

LiranC
  • 2,400
  • 1
  • 27
  • 55
  • 1
    Your image is even used here: http://www.competa.com/blog/oneliner-set-operations-arrays/ - I found that when googling "relative complement javascript" - just rewrite the filter: `let result = [...new Set(B.filter(item => !A.includes(item)))];` – mplungjan Jan 15 '18 at 08:36
  • yes. however, it solves the problem for primitive numbers (loddash function does it too). i am looking for functional approach with a function that can compare. – LiranC Jan 15 '18 at 08:38
  • 1
    Just rewrite the filter part – mplungjan Jan 15 '18 at 08:39
  • In lodash, there's `._differenceBy/With` for this. – georg Jan 15 '18 at 09:11

4 Answers4

3

You could use a comparison function which takes two objects and check the id for unequalness.

var aa = [{ id: 1 }, { id: 2 }],
    bb = [{ id: 2 }, { id: 3 }],
    comparison = (a, b) => a.id !== b.id,
    result = bb.filter(b => aa.every(a => comparison(a, b)));

console.log(result);

With a check for equalness

var aa = [{ id: 1 }, { id: 2 }],
    bb = [{ id: 2 }, { id: 3 }],
    comparison = (a, b) => a.id === b.id,
    result = bb.filter(b => aa.every(a => !comparison(a, b)));

console.log(result);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

You can use array#filter with array#some. Iterate through arrB and check if the arrA contains that id using array#some and negate the result of array#some.

var arrA = [{id: 1},{id:2}],
    arrB = [{id:2},{id:3}],
    result = arrB.filter(({id}) => !arrA.some(o => o.id === id));
console.log(result);
Hassan Imam
  • 21,956
  • 5
  • 41
  • 51
0

You can use array.prototype.filter and array.prototype.findIndex:

var arrayA = [{ id: 1 }, { id: 2 }];
var arrayB = [{ id: 2 }, { id: 3 }];

var result = arrayB.filter(b => arrayA.findIndex(a => a.id === b.id) === -1);
console.log(result);
Faly
  • 13,291
  • 2
  • 19
  • 37
0

If you want to use lodash, _.differenceBy could be of use:

relativeComplementOfAinB = _.differenceBy(arrayB, arrayA, v => v.id);
wensveen
  • 783
  • 10
  • 20