JS 中数组的交集、并集、补集问题

简介: JS 中数组的交集、并集、补集问题

一、背景


1.jpg


如图所示,list 里面有 9 个元素,用户选择的被放进了 selectedList,现在要求出剩余的元素组成的数组 result。实际就是求 selectedList 在 list 中的补集

const list = [1,2,3,4,5,6,7,8,9];
const selectedList = [1,5,9];
function complement (a, b) {
  return a.filter(value => !b.includes(value)).concat(b.filter(value => !a.includes(value)));
}
console.log(complement(list, selectedList)); // [2,3,4,6,7,8]

如果你第一次看到这段代码,一定会蒙圈,我也是。

没关系,接着往下看。


二、补集

1. 概念

补集是差集的一种,完整的说法是绝对差集。


2.jpg


2. 代码拆分

那我们就来拆一下代码:a.filter(value => !b.includes(value)).concat(b.filter(value => !a.includes(value))).concat() 用于合并数组,因此,前后分别是某个数组,这是一个相加的过程。显然,我们弄清楚前面的数组是啥,后面的又是啥,那么整个就明白了。

请看图:


3.jpg


  • a.filter(value => !b.includes(value)) :遍历 a 数组,如果当前元素不在 b 数组中,那么就返回出来。(黑色箭头那一路,属于 a 但不属于 b。)
  • b.filter(value => !a.includes(value)):遍历 b 数组,如果当前元素不在 a 数组中,那么就返回出来。(蓝色箭头那一路,属于 b 但不属于 a。)
  • 所以,执行 complement(list, selectedList) 的过程:list 走黑色箭头,就得到 [2,3,4,6,7,8],而 selectedList 走蓝色箭头,得到 [],之后通过 concat 方法合并起来,得到结果 result => [2,3,4,6,7,8]

3. 小结

综上,补集的写法还可以用 ES6 的剩余运算符来写:

function complement (a, b) {
  return [...a.filter(value => !b.includes(value)), ...b.filter(value => !a.includes(value))];
}


三、差集

1. 概念

差集是相对差集的简称。直接看图。

2. 属于 a,不属于 b

下图所示,是由属于集合 A,但不属于集合 B 的元素组成的集合。


4.jpg


function diff (a, b) {
  return a.filter(value => !b.includes(value));
}

3. 属于 b,不属于 a

下图所示,是由属于集合 B,但不属于集合 A 的元素组成的集合。


5.jpg


function diff (a, b) {
  return b.filter(value => !a.includes(value));
}


四、交集

1. 概念

既属于集合 A,又属于集合 B 的元素,而没有其他元素的集合。


6.jpg


2. 代码

这没啥好说的,利用数组的 filter 方法遍历数组 a,如果当前遍历的元素也在数组 b 中,则将其放入新的数组中,最后返回新的数组即可。

function intersection (a, b) {
  return a.filter(value => b.includes(value));
}


五、并集

1. 概念

集合 A 中所有元素加上集合 B 中所有元素组成的集合。


7.jpg


2. 代码

剩余运算符一把 solo。

function union (a, b) {
  return Array.from(new Set([...a, ...b]));
}


六、对象数组中的常见集合

除了以上简单的情况以外,其实在真实开发中,操作对象数组更常见。

那么,如果列表里的每一个元素是一个对象呢?

const list = [
  {id: '1', name: 'liuyi'},
  {id: '2', name: 'chener'},
  {id: '3', name: 'zhangsan'},
  {id: '4', name: 'lisi'},
  {id: '5', name: 'wangwu'},
  {id: '6', name: 'zhaoliu'},
  {id: '7', name: 'sunqi'},
  {id: '8', name: 'zhouba'},
  {id: '9', name: 'wujiu'},
  {id: '10', name: 'zhengshi'},
];
const selectedList = [
  {id: '1', name: 'liuyi'},
  {id: '5', name: 'wangwu'},
  {id: '9', name: 'wujiu'}
];

1. 补集

从所有订单中删除已付款的订单。


8.jpg


function complement(list, selectedList) {
  return list.reduce(function (pre, cur) {
    if (selectedList.every((item) => item.id !== cur.id)) {
      pre.push({
        name: cur.name
      });
    }
    return pre;
  }, []);
}

2. 交集

function intersection (a, b) {
  let obj = {}
  const arr = [...a, ...b];
  return arr.reduce(function (pre, cur) {
    obj.hasOwnProperty(cur.id) ? pre.push(cur) : (obj[cur.id] = true);
    return pre;
  }, []);
}

3. 并集

function union (a, b) {
  let obj = {};
  const arr = [...a, ...b];
  return arr.reduce(function (pre, cur) {
    if (!obj.hasOwnProperty(cur.id)) {
      pre.push(cur);
    }
    obj[cur.id] = true;
    return pre;
  }, []);
}


七、小结

  • 常见的集合主要有:交集、并集、补集(绝对差集)、差集(相对差集)。



目录
相关文章
|
1月前
|
自然语言处理 前端开发 JavaScript
🛠️ JavaScript数组操作指南:20个精通必备技巧🚀
本文详细介绍了 JavaScript 中的 20 个高效数组操作技巧,涵盖了从基本的添加、移除元素,到数组转换和去重等高级操作。强调了不可变性的重要性,提供了清晰的代码示例,帮助开发者编写更整洁和高效的代码。无论是新手还是经验丰富的开发者,这些技巧都将显著提升您的编码能力,使您在项目中更具竞争力。
23 2
|
1月前
|
JavaScript 前端开发 测试技术
JS都有哪些操作数组的方法
JS都有哪些操作数组的方法
20 3
|
1月前
|
JavaScript
js删除数组中已知下标的元素
js删除数组中已知下标的元素
35 4
|
1月前
|
缓存 JavaScript 前端开发
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
31 1
|
1月前
|
JavaScript 前端开发 Java
【javaScript数组,函数】的基础知识点
【javaScript数组,函数】的基础知识点
23 5
|
1月前
|
JavaScript 前端开发 索引
探索JavaScript数组:基础
探索JavaScript数组:基础
17 3
|
1月前
|
JavaScript 前端开发 索引
JS 删除数组元素( 5种方法 )
JS 删除数组元素( 5种方法 )
37 1
|
1月前
|
JavaScript 前端开发 API
JS中数组的方法flat()怎么用
JS中数组的方法flat()怎么用
13 0
|
1月前
|
JavaScript 前端开发 索引
JavaScript中数组、对象等循环遍历的常用方法介绍(一)
JavaScript中数组、对象等循环遍历的常用方法介绍(一)
21 0
|
1月前
|
前端开发 JavaScript 索引
JavaScript 数组常用高阶函数总结,包括插入,删除,更新,反转,排序等,如map、splice等
JavaScript数组的常用高阶函数,包括遍历、插入、删除、更新、反转和排序等操作,如map、splice、push、pop、reverse等。
18 0