4

I have 2 arrays:

arr1 = [[11,12],[11,13],[11,14], [12,13]];
arr2 = [[11,13],[11,14]];

Expected result [[11,12],[12,13]].

How can I get the difference between the two arrays? I use lodash _.difference but it gives me a wrong answer.

dda
  • 6,030
  • 2
  • 25
  • 34
Truong Cong Hau
  • 151
  • 1
  • 6

4 Answers4

4

You need to use _.differenceWith(), because you need to compare the elements of the sub-arrays. By default, it just tests whether the sub-arrays are the same objects, which they presumably aren't.

result = _.differenceWith(arr1, arr2, _.isEqual);
Barmar
  • 741,623
  • 53
  • 500
  • 612
1

Using just javascript, and only for this and similar examples

var a1 = [[11,12],[11,13],[11,14], [12,13]];
var a2 = [[11,13],[14,11]];
var a3 = a1.filter(ar1 => !a2.some(ar2 => ar1.every(n1 => ar2.includes(n1))))
console.log(a3); // [[11,12],[12,13]]

There are too many criteria to create a generic solution.

For example is [11,12] the same as [12,11], maybe only references to the same array are the same, (ar1 === ar2) as true. What if there are two identical entries in the same array and one in the other, do you filter one out, or keep it? The number of questions can go on for some time and it gets worse the deeper the nesting and the greater the number of types stored in the array.

var a1 = [[11,12],[11,13],[11,14], [12,13]]
var a2 = [[11,13],[14,11],[12,14]];
a3 = [];
[[a1,a2],[a2,a1]].forEach(a=>{
    a3.push(...a[0].filter(
        ar1 => !a[1].some(
            ar2 => ar1.every(
                n1 => ar2.includes(n1)
            )
        )
    ))
});
console.log("[["+a3.join("], [")+"]]")
Blindman67
  • 51,134
  • 11
  • 73
  • 136
  • This only checks `a1` over `a2`. It will fail for the case `var a1 = [[11,12],[11,13],[11,14], [12,13]]; var a2 = [[11,13],[14,11],[12,14]];` – Redu Jan 01 '17 at 12:31
  • @redu That is the point is it not, without a detailed set of rules as to what constitutes equality & inequality, etc... you can only build to a particular test case. There is no solution for this problem that will work for all cases without additional information included as arguments. How many are need? – Blindman67 Jan 01 '17 at 13:08
0

You could do it without lodash. The tip woud be to map subarrays into strings to make comparison easy

var arr1 = [[11,12],[11,13],[11,14], [12,13]];
var arr2 = [[11,13],[11,14],[12,14]];

var res = arr1.concat(arr2).map(x => x.join(",")).filter((x,i,arr) => arr.indexOf(x) === arr.lastIndexOf(x)).map(x => x.split(","));

console.log(res);
kevin ternet
  • 4,514
  • 2
  • 19
  • 27
0

Just a few lines of pure JS is sufficient for this separation (union') job. Besides you should make sure to check both arrays over the other.

var arr1 = [[11,12],[11,13],[11,14],[12,13]],
    arr2 = [[11,13],[11,14],[12,14]];
     res = arr1.reduceRight((p,c,i,a) => { var fi = p.findIndex(s => c.every(n => s.includes(n)));
                                           return fi !== -1 ? (a.splice(i,1),
                                                               p.splice(fi,1),
                                                               p)
                                                            :  p;
                                         },arr2)
               .concat(arr1);
console.log(res);
Redu
  • 25,060
  • 6
  • 56
  • 76