黑马程序员技术交流社区

标题: 【上海校区】js数组并集,交集,差集的计算方式汇总 [打印本页]

作者: frainbowv    时间: 2018-8-1 19:44
标题: 【上海校区】js数组并集,交集,差集的计算方式汇总
前言
今天主要总结一些js数组操作并集,交集,差集的一些方式。发现这些方式在工作用经常遇到,方法有很多种。今天主要总结一下我在工作用通常使用的方式,及一些简单的实现。其实我前面很多文章中都提及了我在工作中用的一些方式。例如:我前面文章讲includes方法,时候就提到了计算交集及差集。还有之前文章去重的方式,其实去重就是取并集的一种方式嘛!
一、new Set 方式实现
这种方式实现起来比较简单,原理就是参考new Set可以去重的功能 ,关于去重可以点击 https://www.haorooms.com/post/qd_ghfx 第17条。
new Set取并集
我封装了一个函数,可以取传入所有数组的并集,函数如下:
[JavaScript] 纯文本查看 复制代码
  //并集
    function unionArray(a,b){
       let tempArray = [];
       for(let i = 0;i<arguments.length;i++){
        tempArray.push(...new Set(arguments))
       }
       return [... new Set(tempArray)]
   }
使用如下:
unionArray([1,2,3,4],[3,4,5,6],[8,8,7,7,6,6,5,5,4,4,3,3]) //(8) [1, 2, 3, 4, 5, 6, 8, 7]new Set取交集
这里也是取2个数组的交集,多的可以自己扩展
[JavaScript] 纯文本查看 复制代码
//交集   function intersect(a,b){
    let set1 = new Set(a),set2 = new Set(b);
      return [...new Set([...set1].filter( x => set2.has(x)))];
   }
使用方式如下:
intersect([1,2,3,4],[3,4,5,6]) //(2) [3, 4]new Set取差集
我这里只是取2个数组的差集,多的大家可以自行扩展。
[JavaScript] 纯文本查看 复制代码
 function difference(a,b){
    let set1 = new Set(a),set2 = new Set(b);
      return [...new Set([...set1].filter(x => !set2.has(x))),...new Set([...set2].filter(x => !set1.has(x)))];
   }
用法如下:
difference([1,2,3,4],[3,4,5,6]) //(4) [1, 2, 5, 6]二、include 方式实现
include方式我之前写过取交集和差集的方式:https://www.haorooms.com/post/es6_string_object_array
今天简单再来列举一下吧:
include取并集
[JavaScript] 纯文本查看 复制代码
function unionArray(a,b){
  let tempArr = a.slice() ;
  b.forEach(v => {!tempArr.includes(v) && tempArr.push(v)})   //tempArr=[1,2,3,4]
  return tempArr
}
用法和上面一样,传2个数组就可以取其并集unionArray([1,2,3,4],[3,4,5,6]); //(6) [1, 2, 3, 4, 5, 6]include方式 数组a和数组b的交集: a.filter(v => b.includes(v))include方式 数组a和数组b的差集:a.concat(b).filter(v => !a.includes(v) || !b.includes(v))
函数自己封装哈,一句话
三、 es5的方式实现
上面的方式用的是ES6,下面我们用ES5实现一下! filter可以实现简单的去重,因此,实现并集也很简单,把数组push到一起(或者连接到一起concat),去重就可以实现并集了。
[JavaScript] 纯文本查看 复制代码
[1,3,4,5,1,2,3,3,4,8,90,3,0,5,4,0].filter(function(elem,index,Array){
   return index === Array.indexOf(elem);
})
当然也可以用indexOf的方式(注:indexOf要考虑NAN或者不考虑NAN 2种情况)
[JavaScript] 纯文本查看 复制代码
//不考虑NAN
var union = a.concat(b.filter(function(v) {
return a.indexOf(v) === -1}))

//考虑可以这么写
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] : [])
交集和差集可以模仿上面include方式,把include改成indexOf
indexOf方式 数组a和数组b的交集:
不考虑NaN(数组中不含NaN)
[JavaScript] 纯文本查看 复制代码
 a.filter(v => b.indexOf(v)!=-1)
考虑的话如下:
[JavaScript] 纯文本查看 复制代码
var aHasNaN = a.some(function(v){ return isNaN(v) })
var bHasNaN = b.some(function(v){ return isNaN(v) })
a.filter(function(v){ return b.indexOf(v) > -1 }).concat(aHasNaN & bHasNaN ? [NaN] : [])
indexOf方式 数组a和数组b的差集:
不考虑NaN(数组中不含NaN)
  
[JavaScript] 纯文本查看 复制代码
 a.concat(b).filter(v => a.indexOf(v) ==-1 || b.indexOf(v)==-1)
考虑的话如下:
[JavaScript] 纯文本查看 复制代码
var aHasNaN = a.some(function(v){ return isNaN(v) })
var bHasNaN = b.some(function(v){ return isNaN(v) })
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] : [])
四、原始方式,假如要兼容IE9及以下版本,可以考虑
[JavaScript] 纯文本查看 复制代码
function array_remove_repeat(a) { // 去重
    var r = [];
    for(var i = 0; i < a.length; i ++) {
        var flag = true;
        var temp = a;
        for(var j = 0; j < r.length; j ++) {
            if(temp === r[j]) {
                flag = false;
                break;
            }
        }
        if(flag) {
            r.push(temp);
        }
    }
    return r;
}

function array_intersection(a, b) { // 交集
    var result = [];
    for(var i = 0; i < b.length; i ++) {
        var temp = b;
        for(var j = 0; j < a.length; j ++) {
            if(temp === a[j]) {
                result.push(temp);
                break;
            }
        }
    }
    return array_remove_repeat(result);
}

function array_union(a, b) { // 并集
    return array_remove_repeat(a.concat(b));
}

function array_difference(a, b) { // 差集 a - b
    //clone = a
    var clone = a.slice(0);
    for(var i = 0; i < b.length; i ++) {
        var temp = b;
        for(var j = 0; j < clone.length; j ++) {
            if(temp === clone[j]) {
                //remove clone[j]
                clone.splice(j,1);
            }
        }
    }
    return array_remove_repeat(clone);
}
另外写一下多维数组转为一维数组的简单方式
[JavaScript] 纯文本查看 复制代码
var arr = [1,[2,[[3,4],5],6]];

function unid(arr){
        var arr1 = (arr + '').split(',');//将数组转字符串后再以逗号分隔转为数组
        var arr2 = arr1.map(function(x){
            return Number(x);
        });
        return arr2;
}
console.log(unid(arr));
文章转载至:https://www.haorooms.com/post/js_array_jiaojicjbj

作者: 不二晨    时间: 2018-8-2 17:36
奈斯,棒棒哒




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2