typescript 循环访问object及其子对象,并在每次子对象中的值更改时基于表达式更新值

hsvhsicv  于 2023-06-07  发布在  TypeScript
关注(0)|答案(1)|浏览(166)

我正在使用Angular 15PrimeNG

{
    id: 1,
    data: {
        value: "Lorem ipsum"
    },
    expression: null,
    subElements: [
        {
            id: 2,
            data: {
                value: 2
            },
            expression: "v0 / v1",
            subElements: [
                {
                    id: 4,
                    data: {
                        value: 100
                    },
                    expression: null,
                    subElements: []
                },
                {
                    id: 5,
                    data: {
                        value: 50
                    },
                    expression: "v0 + v1",
                    subElements: [
                        {
                            id: 6,
                            data: {
                                value: 20
                            },
                            expression: null,
                            subElements: []
                        },
                        {
                            id: 7,
                            data: {
                                value: 30
                            },
                            expression: null,
                            subElements: []
                        }
                    ]
                }
            ]
        },
        {
            id: 3,
            data: {
                value: "Lorem ipsum"
            },
            expression: null,
            subElements: []
        }
    ]
}

例如,如果id为7的对象的值从30更改为40,则根据父对象中的表达式(“v0 + v1”)及其父对象的值(id:2)也应该根据其表达式(“v0 / v1”)进行更新。我使用math.js进行计算。对象嵌套级别的数量不是固定的,并且并非所有对象都具有数值。应忽略非数值对象。我使用p-tree来遍历对象并显示它们的输入。这是我的输入字段:

<p-inputNumber
  [(ngModel)]="node.data.value"
  (onInput)="calculateExpression($event, node)"
  [minFractionDigits]="2"
  [maxFractionDigits]="2"
></p-inputNumber>

我所做的一切都不值得一提。

brccelvz

brccelvz1#

你可以使用后序递归迭代遍历树,并生成一个新的树,其中所有的表达式都被重新求值:

function updateTree(root) {
    if (!root.subElements?.length) return root;
    const subElements = root.subElements.map(updateTree);
    if (!root.expression) return {...root, subElements };
    const scope = Object.fromEntries(subElements.map((node, i) => ["v" + i, node.data?.value]));
    const data = { value: math.evaluate(root.expression, scope) };
    return {...root, subElements, data };
}

// Structure from the question:
const root = {id: 1,data: {value: "Lorem ipsum"},expression: null,subElements: [{id: 2,data: {value: 2},expression: "v0 / v1",subElements: [{id: 4,data: {value: 100},expression: null,subElements: []},{id: 5,data: {value: 50},expression: "v0 + v1",subElements: [{id: 6,data: {value: 20},expression: null,subElements: []},{id: 7,data: {value: 30},expression: null,subElements: []}]}]},{id: 3,data: {value: "Lorem ipsum"},expression: null,subElements: []}]};
// Mutate the value of the node with id 7:
root.subElements[0].subElements[1].subElements[1].data.value = 40; // was 30.
const newRoot = updateTree(root);
console.log(newRoot);
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.8.0/math.js"></script>

如果你需要原始的层次结构被突变为 inplace,那么:

function updateTree(root) {
    root.subElements?.forEach(updateTree);
    if (!root.expression) return;
    const scope = Object.fromEntries(root.subElements.map((node, i) => ["v" + i, node.data?.value]));
    root.data.value = math.evaluate(root.expression, scope);
}

// Structure from the question:
const root = {id: 1,data: {value: "Lorem ipsum"},expression: null,subElements: [{id: 2,data: {value: 2},expression: "v0 / v1",subElements: [{id: 4,data: {value: 100},expression: null,subElements: []},{id: 5,data: {value: 50},expression: "v0 + v1",subElements: [{id: 6,data: {value: 20},expression: null,subElements: []},{id: 7,data: {value: 30},expression: null,subElements: []}]}]},{id: 3,data: {value: "Lorem ipsum"},expression: null,subElements: []}]};
// Mutate the value of the node with id 7:
root.subElements[0].subElements[1].subElements[1].data.value = 40; // was 30.
updateTree(root);
console.log(root);
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.8.0/math.js"></script>

相关问题