数据扁平化处理

155 阅读2分钟

在软件开发过程中,我们时常遇到数据结构与组件构建需求不匹配的情况,尤其是当组件的逻辑较为复杂时。此时,数据预处理成为了衔接数据源与组件间的关键桥梁,而数据扁平化作为其中的一种重要手段,扮演着举足轻重的角色。

那么,让我们尝试着去处理一些简单的数组

例如 let arr = [1, 2, 3, [1, 2, [3, [45, 6, 7]]]]; 数据扁平化

// 1.0 递归形式
const flatten1 = function (arr) {
  let result = [];
  if (!Array.isArray(arr)) throw new Error("参数必须为数组");
  for (let index = 0; index < arr.length; index++) {
    const element = arr[index];
    if (Array.isArray(element)) {
      result = result.concat(flatten1(element));
    } else {
      result.push(element);
    }
  }
  // 返回一个扁平化的数组
  return result;
};
// 2.0 array.flat(depth);
// depth: 可选参数,表示要扁平化的深度。默认值是 1,即只展开一层嵌套, Infinity 表示展开所有嵌套层数。
const flatten2 = (arr) => arr.flat(Infinity);
// 3.0 reduce  array.reduce(callback(accumulator, currentValue[, currentIndex[, array]]), initialValue)
// callback: 必需的。一个函数,对于数组中的每个元素都会被调用一次。它有四个参数:
// accumulator: 必需的。累加器的值是上一次调用回调函数的结果,也是下一次调用回调函数的第一个参数。
// currentValue: 必需的。当前正在处理的数组元素的值。
// currentIndex: 可选的。当前正在处理的数组元素的索引。
// array: 可选的。调用 reduce 方法的数组本身。
// initialValue: 可选的。累积器的初始值。如果没有提供此参数,reduce 会将数组的第一个元素作为初始值,从第二个元素开始遍历数组。
//
const flatten3 = (arr) =>
  arr.reduce(
    (acc, val) => acc.concat(Array.isArray(val) ? flatten3(val) : val),
    []
  );

但是呢,有时候数据结构比较复杂,比如树形结构的数据,需要对其进行展开

例如:let treeData = [ { id: 1, name: "部门1", parentId: 0, children: [ { id: 2, name: "部门2", parentId: 1, children: [ { id: 3, name: "部门3", parentId: 2, children: [], }, ], }, ], }, ];

ok,首先我们使用传统递归的方案来展开树形结构数据

// 1.0 递归形式
const flattenTreeData = function (array) {
  let result = [];
  if (!Array.isArray(array)) throw new Error("参数必须为数组");
  for (let index = 0; index < array.length; index++) {
    const element = array[index];
    result.push(element);
    if (Array.isArray(element.children) && element.children.length > 0) {
      result = result.concat(flattenTreeData(element.children));
    }
  }
  return result;
};
console.log(flattenTreeData(treeData));

使用 reduce 函数来处理

  const flattenTreeData2 = (treeData) => {
  return treeData.reduce((acc, item) => {
    if (Array.isArray(item.children) && item.children.length > 0) {
      // 递归扁平化子节点,并与当前节点一起添加到累积器中
      return [...acc, item, ...flattenTreeData(item.children)];
    } else {
      // 如果没有子节点,直接将当前节点添加到累积器中
      return [...acc, item];
    }
  }, []);
};
console.log(flattenTreeData2(treeData));

好像forEach更加简单,容易理解

const flattenTreeData2 = (treeData) => {
  let result = [];
  treeData.forEach((item) => {
    if (Array.isArray(item.children) && item.children.length > 0) {
      // 递归扁平化子节点,并与当前节点一起添加到累积器中
      result.push(...flattenTreeData(item.children));
    } else {
      // 如果没有子节点,直接将当前节点添加到累积器中
      result.push(item);
    }
  });
  return result;
};
console.log(flattenTreeData2(treeData));