demand scenario
Recently, I have some array operations in my project, which involve some mathematical set operations. I will summarize it after I finish it.
After simplifying the problem, there are two arrays a = [1, 2, 3]
, b = [2, 4, 5]
, to find the union, intersection and difference of a and b arrays.
Method selection
After ES6 and ES7, JS has added some new array methods. If it can be used, it is very good. After all, it is more difficult to write encapsulation functions by yourself.
ES7
ES7 adds an Array.prototype.includes
array method that returns whether an array contains the specified element, combined with the filter method.
var boolean = array.includes(searchElement[, fromIndex])
// 并集
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,4,5]
ES6
A new method in ES6 Array.from
for converting array-like objects and traversable objects into arrays. As long as the class array has length length, it can basically be converted into an array. Combined with Set structure to realize mathematical set solution.
Array.from(arrayLike[, mapFn[, thisArg]])
let aSet = new Set(a)
let bSet = new Set(b)
// 并集
let union = Array.from(new Set(a.concat(b))) // [1,2,3,4,5]
// 交集
let intersection = Array.from(new Set(a.filter(v => bSet.has(v)))) // [2]
// 差集
let difference = Array.from(new Set(a.concat(b).filter(v => !aSet.has(v) || !bSet.has(v)))) // [1,3,4,5]
ES5
ES5 can use filter and indexOf to perform mathematical set operations, but since NaN in the indexOf method always returns -1, compatible processing is required.
- NaNs are not considered (no NaNs in the array)
// 并集
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 }).concat(b.filter(function(v){ return a.indexOf(v) === -1 })) // [1,3,4,5]
- Consider NaNs
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]
// 交集
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(b.filter(function(v){ return a.indexOf(v) === -1 && !isNaN(v) })).concat(aHasNaN ^ bHasNaN ? [NaN] : []) // [1,3,4,5]
Epilogue
Due to the particularity of the JS language, NaN has many problems in the mathematical set operation of arrays. Fortunately, in ES6 and ES7, the new array method solves some of the situations. From a brevity standpoint alone, the ES7 approach is the most concise.
I just don't know that the new standard will be compatible with major browsers until the year of the monkey and the month of the monkey. At present, it is more reliable to use Babel.
Link to this article: https://excaliburhan.com/post/js-set-operation.html
-- EOF --