递归替换层次结构

时间:2020-04-26 11:35:21

标签: javascript node.js json

我有一个像this Github link这样的JSON树

如您所见,该树在每个项目上使用formula属性来计算其值。所以我需要计算几个节点或根节点的值。

您可以看到PL6A,PL6B是带有type = 1的树的结尾。因此,我需要替换树,以便将formula的{​​{1}}构造替换为PLVALUE

示例: ACVALUE公式必须替换为(ACVALUE(PL6A)+ ACVALUE(PL6B))+ ...

我该怎么办,谢谢,抱歉英语不好

更新 我已经尝试过此代码:

PL10

结果是,某些节点运行良好

  for (let i = 0; i < accounts.length; i++) {
    const item = accounts[i];
    let { formula } = accounts[i];

    if (item.children.length && item.type === 2) {
      //Replace formula with full children formula
      item.children.forEach((child) => {
        if (formula.indexOf(child.code) > -1) {
          const fullInfoChild = accounts.find(
            (fullInfoItem) => _.trim(fullInfoItem._id) === _.trim(child._id)
          );

          formula = _.replace(
            formula,
            `PLVALUE(${child.code})`,
            `(${fullInfoChild.formula})`
          );
        }
      });
    } else {
      formula = item.formula;
    }
    accounts[i].formula = formula;
  }

但是,如果我们上某个级别,它就不会像这样

        {
            "_id": "5cf6159f386f5942aabca347",
            "code": "PL10",
            "formula": "(ACVALUE(PL6A)+ACVALUE(PL6B))+(ACVALUE(PL9))+(ACVALUE(PL7B)+ACVALUE(PL7A))+(ACVALUE(PL8A)+ACVALUE(PL8B))+(ACVALUE(DSRGP))",
            "status": 1,
            "type": 2,
            "parents": [
                {
                    "_id": "5cf61756386f5942aabca365",
                    "code": "PL28",
                    "formula": "PLVALUE(PL10)+PLVALUE(PL15)",
                    "status": 1,
                    "type": 2
                }
            ],
            "children": [
                {
                    "_id": "5cf614f4386f5942aabca342",
                    "code": "PL6",
                    "formula": "ACVALUE(PL6A)+ACVALUE(PL6B)",
                    "status": 1,
                    "type": 2
                },
                {
                    "_id": "5cf6156a386f5942aabca346",
                    "code": "PL_DSRGP",
                    "formula": "ACVALUE(DSRGP)",
                    "status": 1,
                    "type": 2
                },
                {
                    "_id": "5cf6152f386f5942aabca345",
                    "code": "PL9",
                    "formula": "ACVALUE(PL9)",
                    "status": 1,
                    "type": 2
                },
                {
                    "_id": "5cf6150e386f5942aabca343",
                    "code": "PL7",
                    "formula": "ACVALUE(PL7B)+ACVALUE(PL7A)",
                    "status": 1,
                    "type": 2
                },
                {
                    "_id": "5cf6151e386f5942aabca344",
                    "code": "PL8",
                    "formula": "ACVALUE(PL8A)+ACVALUE(PL8B)",
                    "status": 1,
                    "type": 2
                }
            ],
            "totalCurrentYear": 0
        },

已更新:将完整的json数据添加到github链接

1 个答案:

答案 0 :(得分:2)

您可以收集对code / formula的引用以及要替换的公式,然后对公式进行迭代以获取值。

var data = [{ _id: "5cf8c78b4aafe73cb56ce424", code: "PL30", formula: "PLVALUE(PL28)+PLVALUE(PL26)", status: 1, type: 2, children: [{ _id: "5cf61756386f5942aabca365", code: "PL28", formula: "PLVALUE(PL10)+PLVALUE(PL15)", status: 1, type: 2 }, { _id: "5cf8c7bd4aafe73cb56ce426", code: "PL26", formula: "PLVALUE(PL23)+PLVALUE(PL24)+PLVALUE(PL25)", status: 1, type: 2 }] }, { _id: "5cf61756386f5942aabca365", code: "PL28", formula: "PLVALUE(PL10)+PLVALUE(PL15)", status: 1, type: 2, children: [{ _id: "5cf6159f386f5942aabca347", code: "PL10", formula: "PLVALUE(PL6)+PLVALUE(PL9)+PLVALUE(PL7)+PLVALUE(PL8)+PLVALUE(PL_DSRGP)", status: 1, type: 2 }, { _id: "5cf61741386f5942aabca364", code: "PL15", formula: "PLVALUE(PL11)+PLVALUE(PL12)+PLVALUE(PL13)+PLVALUE(PL14)", status: 1, type: 2 }], totalCurrentYear: 0 }, { _id: "5cf6159f386f5942aabca347", code: "PL10", formula: "PLVALUE(PL6)+PLVALUE(PL9)+PLVALUE(PL7)+PLVALUE(PL8)+PLVALUE(PL_DSRGP)", status: 1, type: 2, children: [{ _id: "5cf614f4386f5942aabca342", code: "PL6", formula: "ACVALUE(PL6A)+ACVALUE(PL6B)", status: 1, type: 2 }, { _id: "5cf6156a386f5942aabca346", code: "PL_DSRGP", formula: "ACVALUE(DSRGP)", status: 1, type: 2 }, { _id: "5cf6152f386f5942aabca345", code: "PL9", formula: "ACVALUE(PL9)", status: 1, type: 2 }, { _id: "5cf6150e386f5942aabca343", code: "PL7", formula: "ACVALUE(PL7B)+ACVALUE(PL7A)", status: 1, type: 2 }, { _id: "5cf6151e386f5942aabca344", code: "PL8", formula: "ACVALUE(PL8A)+ACVALUE(PL8B)", status: 1, type: 2 }] }, { _id: "5cf614f4386f5942aabca342", code: "PL6", formula: "ACVALUE(PL6A)+ACVALUE(PL6B)", status: 1, type: 2, children: [{ _id: "5cf61869386f5942aabca368", code: "PL6A", type: 1, status: 1 }, { _id: "5cf6187f386f5942aabca36a", code: "PL6B", type: 1, status: 1 }], totalCurrentYear: 0 }],
    replace = (formula, values) => formula.replace(/PLVALUE\(([^\)]+)\)/g, (full, group) => group in values
        ? `(${values[group].object[values[group].key]})`
        : full
    ),
    getNestedValues = (r, object) => {
        r.values[object.code] = { object, key: object.type === 1 ? 'code' : 'formula' };
        if (object.formula?.includes('PLVALUE')) r.formulas.push(object);
        if (object.children) object.children.reduce(getNestedValues, r);
        return r;
    },
    { values, formulas } = data.reduce(getNestedValues, { values: {}, formulas: [] });

// while (formulas.length) { // only if all targets are known
    let i = formulas.length;
    while (i--) {
        let s = replace(formulas[i].formula, values);
        if (s === formulas[i].formula) continue;
        formulas[i].formula = s;
        formulas.splice(i, 1);
    }
// } // only if all targets are known

console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }