javascript - 如何根據帶有表示層級的枚舉列表的字段,將平面陣列轉換為層級樹列表
我正在嘗試將一個平面的帳戶餘額清單轉換為基於唯一代碼清單的層級帳戶樹清單。我對如何解決這個問題感到困惑,因為我看不出應該採取哪些步驟。
如果你想像一個 Excel 表格,那麼帳戶餘額將是一行,而代碼欄位表示該行被拆分成多少層。這實際上意味著,第一個 codes[0] 是第一層,codes[1] 將是下一層,如此類推。通過將帳戶餘額轉換為帳戶樹,我想正確計算每一層(codeType 和 code)的 amountOut,然後將其作為帳戶樹添加到 subAccounts 陣列中。
下面我已經添加了所有使用的類型,並提供了輸入和輸出的範例。
interface AccountBalance {
id: string
codes: Code[]
amountOut: number
}
type Code = {
id: string
codeType: CodeTypes
code: string
description: string
}
enum CodeTypes {
account = "account",
responsible = "responsible",
project = "project",
object = "object",
counterPart = "counterPart",
free = "free",
}
type AccountTree = {
id: string
name: string
code: string
amountOut: number
subAccounts: AccountTree[]
}
輸入範例:
const accountBalances: AccountBalance[] = [
{
id: "671769fbd36fcd6c2c7f2d9b",
codes: [
{
id: "671769fbd36fcd6c2c7f2c2d",
codeType: codeTypeEnum.account,
code: "1250",
description: "Column A",
},
{
id: "671769fbd36fcd6c2c7f2bd5",
codeType: codeTypeEnum.responsible,
code: "17",
description: "Column B",
},
{
id: "671769fbd36fcd6c2c7f2bf7",
codeType: codeTypeEnum.counterPart,
code: "20",
description: "Column C",
},
],
amountOut: 24510549,
},
{
id: "671769fbd36fcd6c2c7f2d9c",
codes: [
{
id: "671769fbd36fcd6c2c7f2c2d",
codeType: codeTypeEnum.account,
code: "1250",
description: "Column A",
},
{
id: "671769fbd36fcd6c2c7f2bee",
codeType: codeTypeEnum.responsible,
code: "40",
description: "Column B",
},
{
id: "671769fbd36fcd6c2c7f2c08",
codeType: codeTypeEnum.counterPart,
code: "S3",
description: "Column C",
},
],
amountOut: 0,
},
{
id: "671769fbd36fcd6c2c7f2d9d",
codes: [
{
id: "671769fbd36fcd6c2c7f2c2d",
codeType: codeTypeEnum.account,
code: "1250",
description: "Column A",
},
{
id: "671769fbd36fcd6c2c7f2bdb",
codeType: codeTypeEnum.responsible,
code: "80",
description: "Column B",
},
{
id: "671769fbd36fcd6c2c7f2bdc",
codeType: codeTypeEnum.counterPart,
code: "52",
description: "Column C",
},
],
amountOut: 6381398,
},
]
我想要的輸出,例如:
const expected: AccountTree = {
id: "671769fbd36fcd6c2c7f2c2d",
name: "Column A",
code: "1250",
amountOut: 30891947,
subAccounts: [
{
id: "671769fbd36fcd6c2c7f2bd5",
name: "Column B",
code: "17",
amountOut: 24510549,
subAccounts: [
{
id: "671769fbd36fcd6c2c7f2bf7",
name: "Column C",
code: "20",
amountOut: 24510549,
subAccounts: [],
},
],
},
{
id: "671769fbd36fcd6c2c7f2bee",
name: "Column B",
code: "40",
amountOut: 0,
subAccounts: [
{
id: "671769fbd36fcd6c2c7f2c08",
name: "Column C",
code: "S3",
amountOut: 0,
subAccounts: [],
},
],
},
{
id: "671769fbd36fcd6c2c7f2bdb",
name: "Column B",
code: "80",
amountOut: 6381398,
subAccounts: [
{
id: "671769fbd36fcd6c2c7f2bdc",
name: "Column C",
code: "52",
amountOut: 6381398,
subAccounts: [],
},
],
},
],
}
到目前為止我得到的是這個
const uniqueCodeTypes = [
...new Set(
accountBalances.reduce<CodeTypes[]>(
(acc, balance) => [
...acc,
...balance.codes.flatMap((code) => code.codeType),
],
[],
),
),
]
const uniqueCodesForCodeType = uniqueCodeTypes.map((codeType) => {
const uniqueCodesForCodeType = [
...new Map(
accountBalances.reduce<Code[]>((acc, balance) => {
const code = balance.codes.find(
(code) => code.codeType === codeType,
)
return code ? [...acc, code] : acc
}, []).map((code) => [code.code, code])
).values(),
]
return uniqueCodesForCodeType
})
但我不確定之後該如何進行。
答案#1
在純 Javascript 中,你可以在同一層級搜尋 id,如果不存在則添加對象。
const
codeTypeEnum = { account: "account", responsible: "responsible", project: "project", object: "object", counterPart: "counterPart", free: "free"},
accountBalances = [{ id: "671769fbd36fcd6c2c7f2d9b", codes: [{ id: "671769fbd36fcd6c2c7f2c2d", codeType: codeTypeEnum.account, code: "1250", description: "Column A" }, { id: "671769fbd36fcd6c2c7f2bd5", codeType: codeTypeEnum.responsible, code: "17", description: "Column B" }, { id: "671769fbd36fcd6c2c7f2bf7", codeType: codeTypeEnum.counterPart, code: "20", description: "Column C" }], amountOut: 24510549 }, { id: "671769fbd36fcd6c2c7f2d9c", codes: [{ id: "671769fbd36fcd6c2c7f2c2d", codeType: codeTypeEnum.account, code: "1250", description: "Column A" }, { id: "671769fbd36fcd6c2c7f2bee", codeType: codeTypeEnum.responsible, code: "40", description: "Column B" }, { id: "671769fbd36fcd6c2c7f2c08", codeType: codeTypeEnum.counterPart, code: "S3", description: "Column C" }], amountOut: 0 }, { id: "671769fbd36fcd6c2c7f2d9d", codes: [{ id: "671769fbd36fcd6c2c7f2c2d", codeType: codeTypeEnum.account, code: "1250", description: "Column A" }, { id: "671769fbd36fcd6c2c7f2bdb", codeType: codeTypeEnum.responsible, code: "80", description: "Column B" }, { id: "671769fbd36fcd6c2c7f2bdc", codeType: codeTypeEnum.counterPart, code: "52", description: "Column C" }], amountOut: 6381398 }],
result = accountBalances.reduce((r, { amountOut, codes }) => {
codes.reduce((level, o) => {
let target = level.find(({ id, codeType }) => id === o.id && codeType === o.codeType);
if (!target) {
target = { ...o, amountOut: 0, subAccounts: [] };
level.push(target);
}
target.amountOut += amountOut;
return target.subAccounts;
}, r);
return r;
}, []);
console.log(result);.as-console-wrapper { max-height: 100% !important; top: 0; }