使用ES6求两个数组(简单数组或对象数组)的并集,交集和差集

简介: 项目中经常有对两个数组的操作,涉及到一些数学中集合的运算.

背景

项目中经常有对两个数组的操作,涉及到一些数学中集合的运算.

集合的定义

集合定义:集合是指具有某种特定性质的具体的或抽象的对象汇总而成的集体。其中,构成集合的这些对象则称为该集合的元素

交集定义:由属于A且属于B的相同元素组成的集合,记作A∩B(或B∩A),读作“A交B”(或“B交A”),即A∩B={x|x∈A,且x∈B}, 如右图所示。注意交集越交越少。若A包含B,则A∩B=B,A∪B=A .

并集定义:由所有属于集合A或属于集合B的元素所组成的集合,记作A∪B(或B∪A),读作“A并B”(或“B并A”),即A∪B={x|x∈A,或x∈B},如下图所示。注意并集越并越多,这与交集的情况正相反 。

编码实战

简单数组

利用ES6中set数组的特性

const aArray = [1, 2, 3, 4, 5];
const bArray = [5, 6, 7, 8, 9];

/**
 * @function 求两个数组的交集
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const intersection = (aArray, bArray) => {
  const bArraySet = new Set(bArray);
  const resultArray = aArray.filter(item => bArraySet.has(item));
  return Array.from(resultArray);
}

/**
 * @function 求两个数组的并集
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const union = (aArray, bArray) => {
  const resultArray = new Set([...aArray, ...bArray]);
  return Array.from(resultArray);
}

/**
 * @function 求两个数组的差集;数组aArray相对于bArray所没有的
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const difference = (aArray, bArray) => {
  const bArraySet = new Set(bArray);
  const resultArray = aArray.filter(item => !bArraySet.has(item));
  return Array.from(resultArray);
}

console.log('aArray: ', aArray);
console.log('bArray: ', bArray);
console.log('并集', union(aArray, bArray));
console.log('交集', intersection(aArray, bArray));
console.log('差集', difference(aArray, bArray));

定义正式集合操作

创建含有集合操作的子类

class XSet extends Set {
  union(...sets) {
    return XSet.union(this, ...sets)
  }
  intersection(...sets) {
    return XSet.intersection(this, ...sets);
  }
  difference(set) {
    return XSet.difference(this, set);
  }
  symmetricDifference(set) {
    return XSet.symmetricDifference(this, set);
  }
  cartesianProduct(set) {
    return XSet.cartesianProduct(this, set);
  }
  powerSet() {
    return XSet.powerSet(this);
  }
  // 返回两个或更多集合的并集
  static union(a, ...bSets) {
    const unionSet = new XSet(a);
    for (const b of bSets) {
      for (const bValue of b) {
        unionSet.add(bValue);
      }
    }
    return unionSet;
  }
  // 返回两个或更多集合的交集
  static intersection(a, ...bSets) {
    const intersectionSet = new XSet(a);
    for (const aValue of intersectionSet) {
      for (const b of bSets) {
        if (!b.has(aValue)) {
          intersectionSet.delete(aValue);
        }
      }
    }
    return intersectionSet;
  }
  // 返回两个集合的差集
  static difference(a, b) {
    const differenceSet = new XSet(a);
    for (const bValue of b) {
      if (a.has(bValue)) {
        differenceSet.delete(bValue);
      }
    }
    return differenceSet;
  }
  // 返回两个集合的对称差集
  static symmetricDifference(a, b) {
    // 按照定义,对称差集可以表达为
    return a.union(b).difference(a.intersection(b));
  }
  // 返回两个集合(数组对形式)的笛卡儿积
  // 必须返回数组集合,因为笛卡儿积可能包含相同值的对
  static cartesianProduct(a, b) {
    const cartesianProductSet = new XSet();
    for (const aValue of a) {
      for (const bValue of b) {
        cartesianProductSet.add([aValue, bValue]);
      }
    }
    return cartesianProductSet;
  }
  // 返回一个集合的幂集
  static powerSet(a) {
    const powerSet = new XSet().add(new XSet());
    for (const aValue of a) {
      for (const set of new XSet(powerSet)) {
        powerSet.add(new XSet(set).add(aValue));
      }
    }
    return powerSet;
  }
}

const aArray = [1, 2, 3, 4, 5];
const bArray = [5, 6, 7, 8, 9];
/**
 * @function 求两个数组的交集
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const intersection = (aArray, bArray) => {
  const aArrayXSet = new XSet(aArray);
  const bArrayXSet = new XSet(bArray);
  const resultArray = aArrayXSet.intersection(bArrayXSet);
  return Array.from(resultArray);
}

/**
 * @function 求两个数组的并集
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const union = (aArray, bArray) => {
  const aArrayXSet = new XSet(aArray);
  const bArrayXSet = new XSet(bArray);
  const resultArray = aArrayXSet.union(bArrayXSet);
  return Array.from(resultArray);
}

/**
 * @function 求两个数组的差集;数组aArray相对于bArray所没有的
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const difference = (aArray, bArray) => {
  const aArrayXSet = new XSet(aArray);
  const bArrayXSet = new XSet(bArray);
  const resultArray = aArrayXSet.difference(bArrayXSet);
  return Array.from(resultArray);
}

console.log('aArray: ', aArray);
console.log('bArray: ', bArray);
console.log('并集', union(aArray, bArray));
console.log('交集', intersection(aArray, bArray));
console.log('差集', difference(aArray, bArray));

对象数组

利用ES6中set数组的特性

const aArray = [
  {
    id: 1,
    desc: 'Number'
  },
  {
    id: 2,
    desc: 'Number'
  },
  {
    id: 3,
    desc: 'Number'
  },
  {
    id: 4,
    desc: 'Number'
  },
  {
    id: 5,
    desc: 'Number'
  }
];
const bArray = [
  {
    id: 5,
    desc: 'Number'
  },
  {
    id: 6,
    desc: 'Number'
  },
  {
    id: 7,
    desc: 'Number'
  },
  {
    id: 8,
    desc: 'Number'
  },
  {
    id: 9,
    desc: 'Number'
  }
];


/**
 * @function 求两个数组的交集
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const intersection = (aArray, bArray) => {
  const bArraySet = new Set(bArray);
  const resultArray = aArray.filter(item => bArraySet.has(item));
  return Array.from(resultArray);
}

/**
 * @function 求两个数组的并集
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const union = (aArray, bArray) => {
  const resultArray = new Set([...aArray, ...bArray]);
  return Array.from(resultArray);
}

/**
 * @function 求两个数组的差集;数组aArray相对于bArray所没有的
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const difference = (aArray, bArray) => {
  const bArraySet = new Set(bArray);
  const resultArray = aArray.filter(item => !bArraySet.has(item));
  return Array.from(resultArray);
}

/**
 * @function  获取集合运算的结果数组
 * @param {string} key 数组对象的唯一标识
 * @param {function} functionAction 需要调用的函数
 * @param {array} aArray
 * @param {array} bArray
 * @returns {array} 正常的数组
 * */
const getResultArray = (key, functionAction, aArray, bArray) => {
  const aArraySimple = aArray.map(i => i[key]); // 根据唯一标识对象数组转换为简单数组
  const bArraySimple = bArray.map(i => i[key]);
  const allData = [...aArray, ...bArray];
  const resultArraySimple = Array.from(functionAction(aArraySimple, bArraySimple));
  return resultArraySimple.map(i => allData.find((j) => j[key] === i));
}

console.log('aArray: ', aArray);
console.log('bArray: ', bArray);
console.log('并集', getResultArray('id', union, aArray, bArray));
console.log('交集', getResultArray('id', intersection, aArray, bArray));
console.log('差集', getResultArray('id', difference, aArray, bArray));

定义正式集合操作

class XSet extends Set {
  union(...sets) {
    return XSet.union(this, ...sets)
  }
  intersection(...sets) {
    return XSet.intersection(this, ...sets);
  }
  difference(set) {
    return XSet.difference(this, set);
  }
  symmetricDifference(set) {
    return XSet.symmetricDifference(this, set);
  }
  cartesianProduct(set) {
    return XSet.cartesianProduct(this, set);
  }
  powerSet() {
    return XSet.powerSet(this);
  }
  // 返回两个或更多集合的并集
  static union(a, ...bSets) {
    const unionSet = new XSet(a);
    for (const b of bSets) {
      for (const bValue of b) {
        unionSet.add(bValue);
      }
    }
    return unionSet;
  }
  // 返回两个或更多集合的交集
  static intersection(a, ...bSets) {
    const intersectionSet = new XSet(a);
    for (const aValue of intersectionSet) {
      for (const b of bSets) {
        if (!b.has(aValue)) {
          intersectionSet.delete(aValue);
        }
      }
    }
    return intersectionSet;
  }
  // 返回两个集合的差集
  static difference(a, b) {
    const differenceSet = new XSet(a);
    for (const bValue of b) {
      if (a.has(bValue)) {
        differenceSet.delete(bValue);
      }
    }
    return differenceSet;
  }
  // 返回两个集合的对称差集
  static symmetricDifference(a, b) {
    // 按照定义,对称差集可以表达为
    return a.union(b).difference(a.intersection(b));
  }
  // 返回两个集合(数组对形式)的笛卡儿积
  // 必须返回数组集合,因为笛卡儿积可能包含相同值的对
  static cartesianProduct(a, b) {
    const cartesianProductSet = new XSet();
    for (const aValue of a) {
      for (const bValue of b) {
        cartesianProductSet.add([aValue, bValue]);
      }
    }
    return cartesianProductSet;
  }
  // 返回一个集合的幂集
  static powerSet(a) {
    const powerSet = new XSet().add(new XSet());
    for (const aValue of a) {
      for (const set of new XSet(powerSet)) {
        powerSet.add(new XSet(set).add(aValue));
      }
    }
    return powerSet;
  }
}

const aArray = [
  {
    id: 1,
    desc: 'Number'
  },
  {
    id: 2,
    desc: 'Number'
  },
  {
    id: 3,
    desc: 'Number'
  },
  {
    id: 4,
    desc: 'Number'
  },
  {
    id: 5,
    desc: 'Number'
  }
];
const bArray = [
  {
    id: 5,
    desc: 'Number'
  },
  {
    id: 6,
    desc: 'Number'
  },
  {
    id: 7,
    desc: 'Number'
  },
  {
    id: 8,
    desc: 'Number'
  },
  {
    id: 9,
    desc: 'Number'
  }
];

/**
 * @function 求两个数组的交集
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const intersection = (aArray, bArray) => {
  const aArrayXSet = new XSet(aArray);
  const bArrayXSet = new XSet(bArray);
  const resultArray = aArrayXSet.intersection(bArrayXSet);
  return Array.from(resultArray);
}

/**
 * @function 求两个数组的并集
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const union = (aArray, bArray) => {
  const aArrayXSet = new XSet(aArray);
  const bArrayXSet = new XSet(bArray);
  const resultArray = aArrayXSet.union(bArrayXSet);
  return Array.from(resultArray);
}

/**
 * @function 求两个数组的差集;数组aArray相对于bArray所没有的
 * @description 数组为简单数组
 * @returns {array} 正常的数组
 * */
const difference = (aArray, bArray) => {
  const aArrayXSet = new XSet(aArray);
  const bArrayXSet = new XSet(bArray);
  const resultArray = aArrayXSet.difference(bArrayXSet);
  return Array.from(resultArray);
}

/**
 * @function  获取集合运算的结果数组
 * @param {string} key 数组对象的唯一标识
 * @param {function} functionAction 需要调用的函数
 * @param {array} aArray
 * @param {array} bArray
 * @returns {array} 正常的数组
 * */
const getResultArray = (key, functionAction, aArray, bArray) => {
  const aArraySimple = aArray.map(i => i[key]); // 根据唯一标识对象数组转换为简单数组
  const bArraySimple = bArray.map(i => i[key]);
  const allData = [...aArray, ...bArray];
  const resultArraySimple = Array.from(functionAction(aArraySimple, bArraySimple));
  return resultArraySimple.map(i => allData.find((j) => j[key] === i));
}

console.log('aArray: ', aArray);
console.log('bArray: ', bArray);
console.log('并集', getResultArray('id', union, aArray, bArray));
console.log('交集', getResultArray('id', intersection, aArray, bArray));
console.log('差集', getResultArray('id', difference, aArray, bArray));
相关文章
|
JavaScript 前端开发
VUE element-ui之table表格自增序号(前端实现)
VUE element-ui之table表格自增序号(前端实现)
2126 0
|
SQL XML Java
【mybatis】第二篇:@Select注解中加入字段判断
【mybatis】第二篇:@Select注解中加入字段判断
|
应用服务中间件 nginx
Nuxt 获取当前域名
Nuxt 获取当前域名
|
9月前
|
前端开发 JavaScript API
前端大佬都在用的usePagination究竟有多强?
usePagination 是 alovajs 提供的一款强大的分页请求工具,专为简化分页场景而生。它能自动管理分页数据、支持预加载、追加模式以及丰富的列表操作函数,极大提升开发效率与用户体验。作为下一代请求工具,alovajs 不仅涵盖 15+ 请求策略,还通过状态化数据和特定事件减少代码量。无论是下拉加载还是翻页优化,usePagination 都能轻松应对。如果你正在寻找高效的分页解决方案,不妨试试这个贴心的工具!
|
编解码 索引
RTMP 和 HLS 协议的优缺点
【10月更文挑战第26天】RTMP和HLS协议各有优缺点,在选择使用哪种协议时,需要根据具体的直播场景、观众群体、设备兼容性、服务器性能等因素进行综合考虑,以选择最适合的直播协议。
|
Dart API Android开发
Flutter 3.24 中的新功能
Flutter 3.24 已发布,带来诸多新功能与改进。此版本亮点包括:GPU 预览版,支持高级图形和 3D 场景;Web 应用多视图嵌入,增强应用灵活性;新增视频广告变现支持,助您增加收益。框架方面,引入新 Slivers 组件、Cupertino 库更新及 TreeView 小部件。引擎改进包括 Impeller 性能提升和默认图像质量优化。此外,新增重建统计功能,改善开发工具体验。此版本还支持 Swift 包管理器,并对 Navigator 等进行了破坏性变更。感谢社区贡献,期待您的精彩创作!
432 0
Flutter 3.24 中的新功能
|
Prometheus 监控 Cloud Native
Prometheus:Java调用PromQL工具类(瞬时数据查询)
Prometheus:Java调用PromQL工具类(瞬时数据查询)
Prometheus:Java调用PromQL工具类(瞬时数据查询)
|
开发者
Flutter笔记:Widgets Easier组件库(12)使用消息吐丝(Notify Toasts)
Flutter笔记:Widgets Easier组件库(12)使用消息吐丝(Notify Toasts)
225 0
|
JavaScript
原生js实现文件下载并设置请求头header
原生js实现文件下载并设置请求头header
374 0