数据结构转换

import { Injectable } from '@nestjs/common';

@Injectable()
export class Array2Tree2SumArray {
  /**
    * 数组数据结构转换,汇总项置顶并汇总
    * @param p_data 
    * @param p_fieldArray 
    * @param p_sumField 
    * @returns 
    * 
     const startYear = 2020;
     const endYear = 2021;
     let title: string[] = ['mainType', 'subType'];
     const userDefined = "KK";
     let sumField: string[] = [];
     for (let i = startYear; i <= endYear; i++) {
       sumField.push(`plan_${i}`)
     }
 
     let data = [
       { "mainType": "AAA", "subType": "A_sub_1", "KK": "D_1", "plan_2020": 1000, "plan_2021": 2000 },
       { "mainType": "AAA", "subType": "A_sub_1", "KK": "D_2", "plan_2020": null, "plan_2021": null },
       { "mainType": "AAA", "subType": "A_sub_2", "KK": "D_3", "plan_2020": null, "plan_2021": null },
       { "mainType": "AAA", "subType": "A_sub_2", "KK": "D_4", "plan_2020": null, "plan_2021": null },
       { "mainType": "BBB", "subType": "B_sub_1", "KK": "D_5", "plan_2020": null, "plan_2021": null },
       { "mainType": "BBB", "subType": "B_sub_1", "KK": "D_6", "plan_2020": null, "plan_2021": null }
     ]
     this.changeArray(data, title, sumField, userDefined);
    * 
    */
  changeArray(p_data: any[], p_fieldArray: string[], p_sumField: string[], p_userDefined: string): any {
    //转换数组为树形结构
    let objTree = this.converArrayToObjectTree(p_data, p_fieldArray, p_sumField, p_userDefined);
    //递归逐层汇总
    this.calcSum({ obj: objTree }, p_sumField);
    let result = this.converTreeToArray(objTree, p_sumField, p_userDefined);
    return result;
  }



  /**
   * 转换数组为树形结构
   * @param p_data 数组
   * @param p_fieldArray 树形节点数组,顺序从根往叶方向
   * @returns 树形结构
   */
  converArrayToObjectTree(p_data: any[], p_fieldArray: string[], p_sumField: string[], p_userDefined: string): any {

    //挪出一个节点
    let filed = p_fieldArray.shift();
    let result: any = {
      level: 1
    }
    let titleArray: string[] = [];
    p_data.map(x => {
      let title = x[filed];
      if (titleArray.findIndex(y => y === title) < 0)
        titleArray.push(title)
      if (!result[title]) {
        result[title] = {
          data: []
        };
      }
      let newObj: any = {};
      for (let tmpName in x) {
        if (tmpName === p_userDefined || p_sumField.indexOf(tmpName) >= 0 || p_fieldArray?.indexOf(tmpName) >= 0) {
          newObj[tmpName] = x[tmpName]
        }
      }
      (result[title].data as any[]).push(newObj);
    });
    if (p_fieldArray?.length > 0 && titleArray?.length > 0) {
      result.level += 1;//记录,增加层级下沉
      titleArray.forEach(x => {
        if ((result[x].data as any[])?.length > 0) {
          result[x].obj = this.converArrayToObjectTree(JSON.parse(JSON.stringify(result[x].data)), JSON.parse(JSON.stringify(p_fieldArray)), p_sumField, p_userDefined);
          result[x].data = undefined;
        }
      });
    }
    return result;
  }
  calcSum(p_data: any, p_sumField: string[]) {

    if (p_data.data !== undefined) {
      //叶节点
      (p_data.data as any[]).map(x => {
        p_sumField.forEach(y => {
          p_data[y] = p_data[y] ?? 0;
          p_data[y] += Number(x[y] ?? 0);
        });
      });
      return;
    }
    else {
      for (let tmpName in p_data.obj) {
        if (tmpName !== 'level')
          this.calcSum(p_data.obj[tmpName], p_sumField)
      }
      p_sumField.forEach(y => {
        p_data[y] = p_data[y] ?? 0;
        for (let tmpName in p_data.obj) {
          p_data[y] += Number(p_data.obj[tmpName][y] ?? 0);
        }
      });

    }

  }
  converTreeToArray(p_tree: any, p_sumField: string[], p_userDefined: string): any[] {
    let result: any[] = [];

    if (p_tree[p_userDefined] === undefined) {
      for (let tmpName in p_tree) {
        if (tmpName === 'level') continue;
        let tmpNode = p_tree[tmpName];
        let tmpRow: any = {
          level: p_tree.level
        }
        tmpRow[p_userDefined] = tmpName;
        p_sumField.map(x => {
          tmpRow[x] = tmpNode[x];
        });
        result.push(tmpRow);
        if (tmpNode.obj) {
          let tmpNodeChildren = this.converTreeToArray(JSON.parse(JSON.stringify(tmpNode.obj)), p_sumField, p_userDefined);
          tmpNodeChildren.map(y => {
            result.push(y);
          });
        }

        if (tmpNode.data) {
          //叶节点的上一个节点
          (tmpNode.data as any[])?.forEach(leaf => {
            let leafInfo: any = {}
            leafInfo[p_userDefined] = leaf[p_userDefined];
            p_sumField.map(y => {
              leafInfo[y] = leaf[y]
            })
            result.push(leafInfo);
          })
        }
      }
    }
    return result;
  }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值