JS array union, intersection and difference

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.includesarray 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.fromfor 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 --

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326342894&siteId=291194637