TypeScript应用数组reduce和对象map将扁平化数据转为树形结构

export class TreeHelper {
  /**
   *
   * @param items 扁平数据数组
   * @param idMapper 数组元素的id映射
   * @param parentIdMapper 数组元素的父节点id映射
   * @param objectMapper 数组元素映射为另一种类型的对象,默认为undefined,即使用源对象类型
   * @returns 树形数据数组
   */
  public static arrayToTree<S, T>(
    items: any[],
    idMapper: (item: S) => string | number,
    parentIdMapper: (item: S) => string | number,
    objectMapper: (item: S) => T = undefined,
    childrenProperty: string = 'children'
  ) {
    // 已数据id为属性的map,用于暂存数据和快速存取父元素
    const map = {};

    // 使用数组的reduce过程,逐个循环,收敛结果到第一层数组
    const tree = items.reduce((prev: T[], curr: S) => {
      // 生成新的元素
      const tmp = objectMapper ? objectMapper(curr) : curr;
      const newItem: any = { ...tmp } as T;

      // 对树形元素的子树数组赋值,
      // 由于是一次循环,有可能在前面已经找到子节点,从而先创建了父节点,
      // 所以如果在map中找到当前id为属性的节点,需要将子树合并过来
      const id = idMapper(curr);
      newItem[childrenProperty] = map.hasOwnProperty(id) ? map[id][childrenProperty] : [];
      // 将当前节点放回map中
      map[id] = newItem;

      // 寻找找父节点
      let parentId = parentIdMapper(curr);
      if (!parentId) {
        // 如果不存在父节点,则将当前节点放入第一层
        prev.push(newItem);
      } else {
        // 如果存在父节点,则将当前节点放到父节点的子树中
        if (!map.hasOwnProperty(parentId)) {
          // 如果map中不存在父节点,则先创建一个临时的父节点
          map[parentId] = {};
          map[parentId][childrenProperty] = [];
        }
        map[parentId][childrenProperty].push(newItem);
      }
      // 返回第一层数组,继续归并下一个元素
      return prev;
    }, []);

    return tree;
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值