← 中文资源

简体中文版本

数组压缩与分区

把多个平行数组合并为元组数组,并按谓词把集合拆成通过与否两组,支持短缺填充。

阅读英文原文

功能说明

zipArrays 把多个平行数组按相同下标合并为元组,长度取最短者,适合把表头与行数据、键与值、坐标数组组合起来。zipLongest 取最长长度并用填充值补齐短缺数组,适合可空列。partitionArray 用一次遍历把集合拆成谓词为真和为假的两组,比连续两次 filter 更省遍历。返回的都是新数组。

关键代码

zipArrays 用 Math.min 计算共同长度,再逐下标映射每个数组;空参数直接返回空数组。zipLongest 把填充值放在第一个参数,后面接收任意数量数组,用 index 与各数组长度比较决定取值。partitionArray 校验数组和谓词,forEach 中调用谓词并传入值、下标与原数组,依据结果推入两个桶,最后以二元组返回。

使用注意

zipArrays 静默丢弃超长数组的尾部元素,若数据完整性重要应先校验长度一致或改用 zipLongest。zipLongest 的填充值参数在只传一个参数时会被当作数组,调用时需明确传入填充值。partitionArray 的谓词应保持纯粹,不要在内部修改原数组。三个函数都不做深拷贝,元组中保存的是原元素引用。

验证方式

测试等长数组、长短不一、空数组与无参数调用,确认 zipArrays 截断、zipLongest 补齐。验证填充值为 null、零和对象时的引用行为。分区函数测试空数组、全部为真、全部为假与混合数据,确认保持原顺序。再测试谓词接收下标和原数组,以及非数组、非函数参数会抛出类型错误。

代码示例

export function zipArrays(...arrays) {
  if (arrays.length === 0) return [];
  const length = Math.min(...arrays.map((array) => array.length));
  const result = [];
  for (let index = 0; index < length; index += 1) {
    result.push(arrays.map((array) => array[index]));
  }
  return result;
}

export function zipLongest(fillValue = null, ...arrays) {
  const length = Math.max(0, ...arrays.map((array) => array.length));
  const result = [];
  for (let index = 0; index < length; index += 1) {
    result.push(arrays.map((array) => (index < array.length ? array[index] : fillValue)));
  }
  return result;
}

export function partitionArray(values, predicate) {
  if (!Array.isArray(values)) throw new TypeError("values must be an array");
  if (typeof predicate !== "function") throw new TypeError("predicate must be a function");
  const truthy = [];
  const falsy = [];
  values.forEach((value, index) => {
    if (predicate(value, index, values)) truthy.push(value);
    else falsy.push(value);
  });
  return [truthy, falsy];
}