轉(zhuǎn):
https://excaliburhan.com/post/js-set-operation.html
需求場景
最近,自己項目中有一些數(shù)組操作,涉及到一些數(shù)學(xué)集的運算,趁著完成后總結(jié)一下。
簡化問題之后,現(xiàn)有兩數(shù)組a = [1, 2, 3],b = [2, 4, 5],求a,b數(shù)組的并集,交集和差集。
方法選擇
JS在ES6,ES7之后,新增了一些數(shù)組方法,如果能夠使用,那是極好的,畢竟自己寫封裝函數(shù)還是比較辛苦的。
ES7
ES7新增了一個Array.prototype.includes的數(shù)組方法,用于返回一個數(shù)組是否包含指定元素,結(jié)合filter方法。
var boolean = array.includes(searchElement[, fromIndex])
// 并集
letunion = a.concat(b.filter(v=>!a.includes(v)))// [1,2,3,4,5]
// 交集
letintersection = a.filter(v=>b.includes(v))// [2]
// 差集
letdifference = a.concat(b).filter(v=>!a.includes(v) || !b.includes(v))// [1,3,4,5]
js
ES6
ES6中新增的一個Array.from方法,用于將類數(shù)組對象和可遍歷對象轉(zhuǎn)化為數(shù)組。只要類數(shù)組有l(wèi)ength長度,基本都可以轉(zhuǎn)化為數(shù)組。結(jié)合Set結(jié)構(gòu)實現(xiàn)數(shù)學(xué)集求解。
Array.from(arrayLike[, mapFn[, thisArg]])
letaSet =newSet(a)
letbSet =newSet(b)
// 并集
letunion =Array.from(newSet(a.concat(b)))// [1,2,3,4,5]
// 交集
letintersection =Array.from(newSet(a.filter(v=>bSet.has(v))))// [2]
// 差集
letdifference =Array.from(newSet(a.concat(b).filter(v=>!aSet.has(v) || !bSet.has(v))))// [1,3,4,5]
js
ES5
ES5可以利用filter和indexOf進(jìn)行數(shù)學(xué)集操作,但是,由于indexOf方法中NaN永遠(yuǎn)返回-1,所以需要進(jìn)行兼容處理。
不考慮NaN(數(shù)組中不含NaN)
// 并集
varunion = a.concat(b.filter(function(v){
returna.indexOf(v) ===-1}))// [1,2,3,4,5]
// 交集
varintersection = a.filter(function(v){returnb.indexOf(v) >-1})// [2]
// 差集
vardifference = a.filter(function(v){returnb.indexOf(v) ===-1}).concat(b.filter(function(v){returna.indexOf(v) ===-1}))// [1,3,4,5]
js
考慮NaN
varaHasNaN = a.some(function(v){returnisNaN(v) })
varbHasNaN = b.some(function(v){returnisNaN(v) })
// 并集
varunion = a.concat(b.filter(function(v){
returna.indexOf(v) ===-1&& !isNaN(v)})).concat(!aHasNaN & bHasNaN ? [NaN] : [])// [1,2,3,4,5]
// 交集
varintersection = a.filter(function(v){returnb.indexOf(v) >-1}).concat(aHasNaN & bHasNaN ? [NaN] : [])// [2]
// 差集
vardifference = a.filter(function(v){returnb.indexOf(v) ===-1&& !isNaN(v) }).concat(b.filter(function(v){returna.indexOf(v) ===-1&& !isNaN(v) })).concat(aHasNaN ^ bHasNaN ? [NaN] : [])// [1,3,4,5]
js
結(jié)語
由于JS語言的特殊性,NaN在數(shù)組的數(shù)學(xué)集操作中有不少問題,好在ES6和ES7中,新的數(shù)組方法解決了部分情況。單從簡潔性來看,ES7的方法最簡潔明了。
就是不知道新的標(biāo)準(zhǔn)要猴年馬月才能被各大瀏覽器兼容,目前還是使用Babel比較靠譜。