JavaScript数组求并集,交集和差集

现有两数组 a = [1, 2, 3],b = [2, 4, 5],求 a,b 数组的并集,交集和差集。

1、ES7 方法

ES7 新增了一个 Array.prototype.includes 的数组方法,用于返回一个数组是否包含指定元素,结合 filter 方法。

1
2
3
4
5
6
// 并集
let union = a.concat(b.filter((v) => !a.includes(v))); // [1,2,3,4,5]
// 交集
let intersection = a.filter((v) => b.includes(v)); // [2]
// 差集
let difference = a.concat(b).filter((v) => a.includes(v) && !b.includes(v)); // [1,3]
2、ES6 方法

ES6 中新增的一个 Array.from 方法,用于将类数组对象和可遍历对象转化为数组。只要类数组有 length 长度,基本都可以转化为数组。结合 Set 结构实现数学集求解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let a = [1, 2, 3];
console.log(a);

let b = [2, 4, 5];

let aSet = new Set(a);
let bSet = new Set(b);

// 并集
let union = Array.from(new Set(a.concat(b))); // [1,2,3,4,5]
console.log(union);

// 交集
let intersection = Array.from(
new Set(a.filter((v) => bSet.has(v))) // [2]
);

// 差集
let differenceNew = Array.from(
new Set(a.concat(b).filter((v) => aSet.has(v) && !bSet.has(v)))[(1, 3)]
);
console.log(differenceNew);
ES5 方法

ES5 可以利用 filter 和 indexOf 进行数学集操作,但是,由于 indexOf 方法中 NaN 永远返回-1,所以需要进行兼容处理。

01 不考虑NaN(数组中不含NaN)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var a = [1, 2, 3];
var b = [2, 4, 5];

// 并集
var union = a.concat(
b.filter(function (v) {
return a.indexOf(v) === -1;
})
); // [1,2,3,4,5]
// 交集
var intersection = a.filter(function (v) {
return b.indexOf(v) > -1;
}); // [2]

// 差集
var difference = a.filter(function (v) {
return b.indexOf(v) === -1;
}); // [1,3]

console.log(union);
console.log(intersection);
console.log(difference);

02 考虑NaN(数组中含NaN)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
var a = [1, 2, 3, NaN];
var b = [2, 4, 5];

var aHasNaN = a.some(function (v) {
return isNaN(v);
});
var bHasNaN = b.some(function (v) {
return isNaN(v);
});

// 并集
var union = a
.concat(
b.filter(function (v) {
return a.indexOf(v) === -1 && !isNaN(v);
})
)
.concat(!aHasNaN & bHasNaN ? [NaN] : []); // [1,2,3,4,5,NaN]

// 交集
var intersection = a
.filter(function (v) {
return b.indexOf(v) > -1;
})
.concat(aHasNaN & bHasNaN ? [NaN] : []); // [2]

// 差集
var difference = a
.filter(function (v) {
return b.indexOf(v) === -1 && !isNaN(v);
})
.concat(aHasNaN && !bHasNaN ? [NaN] : []); //1,3,NaN

console.log(union);
console.log(intersection);
console.log(difference);

filter 完成数组去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var r;
var arr = [
"apple",
"strawberry",
"banana",
"pear",
"apple",
"orange",
"orange",
"strawberry",
];

r = arr.filter(function (element, index, self) {
return self.indexOf(element) === index;
});

alert(r);
// 去除重复元素依靠的是indexOf总是返回第一个元素的位置,后续的重复元素位置与indexOf返回的位置不相等,因此被filter滤掉了。