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;
}
}