使用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));
上一篇:微软为Office套件开发出语音听写软件


下一篇:阿里云服务器如何选择带宽?