# 数组交集

function baseIntersection (arrays, iteratee) {
  const includes = arrayIncludes;
  const length = arrays[0].length; 
  const othLength = arrays.length; // 获取传入的数组数量
  const result = [];
  
  let array;
  let maxLength = Infinity;
  let othIndex = othLength;
  
  // 遍历数组,寻找数组元素最少的那组元素个数——交集数量
  while (othIndex--) {
    array = arrays[othIndex];
    if (othIndex && iteratee) {
      array = map(array, (value) => iteratee(value));
    }
    maxLength = Math.min(array.length, maxLength);
  }
  
	array = arrays[0];
	let index = -1;

  // 以第一个数组为基准,如果它存在的元素,其他元素也存在,则为交集元素,否则不为交集元素。
  outer:
  while(++index < length && result.length < maxLength) {
    let value = array[index]; // 将第一个数组每一项依次取出
		const computed = iteratee ? iteratee(value) : value;
    
    if (!includes(result, computed)) { // 去重,重复元素不算交集
      othIndex = othLength; // 初始化为数组的总长度
      while(--othIndex) { // 从后向前遍历传入的数组
        if (!includes(arrays[othIndex], computed)) { // 如果这个元素只要不在其中一个数组中,就跳出循环
          continue outer;
        }
      }
      result.push(value);
    }
  }
}

这段代码有点复杂,需要多看几遍。

需求:寻找N个数组共同存在的交集元素。

核心思想如下:

如果某个元素是arrays的交集元素,则此元素肯定存在于所有的arrays中,也肯定存在于第一个数组中。反之,如果在第一个数组中不存在的元素,肯定不是交集元素。

因此,根据这个特征,我们可以以第一个数组为标准,将第一个数组的元素依次取出,如果这个元素在其他数组都存在,那么这个元素肯定是交集元素。

# 值得回味的代码

# 确定交集长度

  while (othIndex--) {
    array = arrays[othIndex];
    if (othIndex && iteratee) {
      array = map(array, (value) => iteratee(value));
    }
    maxLength = Math.min(array.length, maxLength);
  }

这段代码,能够确定最后交集数组的长度,因为这些数组中最短的长度,就是最后交集数组的长度。可以参考上面那段话,仔细回味一下。

# 验证是否为交集元素

if (!includes(result, computed)) { // 去重,重复元素不算交集
  othIndex = othLength; // 初始化为数组的总长度
  while(--othIndex) { // 从后向前遍历传入的数组
    if (!includes(arrays[othIndex], computed)) { // 如果这个元素只要不在其中一个数组中,就跳出循环
      continue outer;
    }
  }
  result.push(value);
}

这段代码的第一句,就保证了交集去重。当元素已经存在于交集中时,不再进行判断。

然后获取传入的数组总个数,因为第一组的元素,每一次循环都需要在余下所有数组中查找是否存在。而--othIndex为0时,就会结束循环,能够保证不会循环到第一个数组(第一个数组为参照数组)。

当元素在其他任意一个数组中不存在,表示此元素不为交集元素。

# 亮点

无论第一个数组是否为最短的,但是第一个(任意一个)数组中肯定是存在完整的交集结果。因此只需要知道最后交集的长度,就可以取得完整的交集数据。

可以说非常厉害了,值得回味。

最近更新时间: 2020/9/6 11:30:38