英文:
Recursively update parent child info based on key passed
问题
以下是您提供的代码和说明的翻译:
我有一个看起来像这样的对象数组,
const data = [
{
key: "id1",
name: "Category 1",
curr: 0,
total: 0,
nodes: [
{
key: "id2",
name: "Applications",
curr: 20,
total: 30,
nodes: [
{
key: "id3",
name: "Gaming",
curr: 5,
total: 10,
nodes: []
},
{
key: "id4",
name: "Operating System",
curr: 15,
total: 20,
nodes: []
}
]
}
]
},
{
key: "id5",
name: "Category 2",
curr: 0,
total: 0,
nodes: [
{
key: "id6",
name: "Sub Category",
curr: 12,
total: 48,
nodes: [
{
key: "id7",
name: "Inside Sub",
curr: 12,
total: 48,
nodes: []
}
]
}
]
},
{
key: "id8",
name: "Last One",
curr: 0,
total: 0,
nodes: []
}
];
每个级别的 key
属性在整个树中都是唯一的。当我将键和此数组传递给一个函数时,它应该递增匹配键级别的 curr
值,此递增应该一直延伸到级别 1。请注意,不应更新级别 0 的项目。所以基本上当我传递 incrementRecursively(data, "id4")
时,输出应该如下所示,
const output = [
{
key: "id1",
name: "Category 1",
curr: 0,
total: 0,
nodes: [
{
key: "id2",
name: "Applications",
curr: 21,
total: 30,
nodes: [
{
key: "id3",
name: "Gaming",
curr: 5,
total: 10,
nodes: []
},
{
key: "id4",
name: "Operating System",
curr: 16,
total: 20,
nodes: []
}
]
}
]
},
{
key: "id5",
name: "Category 2",
curr: 0,
total: 0,
nodes: [
{
key: "id6",
name: "Sub Category",
curr: 12,
total: 48,
nodes: [
{
key: "id7",
name: "Inside Sub",
curr: 12,
total: 48,
nodes: []
}
]
}
]
},
{
key: "id8",
name: "Last One",
curr: 0,
total: 0,
nodes: []
}
];
我尝试的代码如下,
const incrementRecursively = (nodes, key) => {
const increment = (nodes, key) => {
nodes.forEach((node) => {
if (node.key === key) {
node.curr++;
}
if (node.nodes.length) {
increment(node.nodes, key);
}
});
};
increment(nodes, key);
return nodes;
};
有人能帮助我如何更新父级而不递增根值吗?
如果您需要更多帮助或有其他问题,请随时提出。
<details>
<summary>英文:</summary>
I have an array of object that look this,
const data = [
{
key: "id1",
name: "Category 1",
curr: 0,
total: 0,
nodes: [
{
key: "id2",
name: "Applications",
curr: 20,
total: 30,
nodes: [
{
key: "id3",
name: "Gaming",
curr: 5,
total: 10,
nodes: []
},
{
key: "id4",
name: "Operating System",
curr: 15,
total: 20,
nodes: []
}
]
}
]
},
{
key: "id5",
name: "Category 2",
curr: 0,
total: 0,
nodes: [
{
key: "id6",
name: "Sub Category",
curr: 12,
total: 48,
nodes: [
{
key: "id7",
name: "Inside Sub",
curr: 12,
total: 48,
nodes: []
}
]
}
]
},
{
key: "id8",
name: "Last One",
curr: 0,
total: 0,
nodes: []
}
];
`key` property at each level is unique across the entire tree. When I pass in key and this array to a functon, it should increment the `curr` value at the matching key level and this increment should go all the way upto level 1. Note that level 0 items should not be updated. So basically when I pass `incrementRecursively(data, "id4")`, the output should look like,
const output = [
{
key: "id1",
name: "Category 1",
curr: 0,
total: 0,
nodes: [
{
key: "id2",
name: "Applications",
curr: 21,
total: 30,
nodes: [
{
key: "id3",
name: "Gaming",
curr: 5,
total: 10,
nodes: []
},
{
key: "id4",
name: "Operating System",
curr: 16,
total: 20,
nodes: []
}
]
}
]
},
{
key: "id5",
name: "Category 2",
curr: 0,
total: 0,
nodes: [
{
key: "id6",
name: "Sub Category",
curr: 12,
total: 48,
nodes: [
{
key: "id7",
name: "Inside Sub",
curr: 12,
total: 48,
nodes: []
}
]
}
]
},
{
key: "id8",
name: "Last One",
curr: 0,
total: 0,
nodes: []
}
];
The code that I tried,
const incrementRecursively = (nodes, key) => {
const increment = (nodes, key) => {
nodes.forEach((node) => {
if (node.key === key) {
node.curr++;
}
if (node.nodes.length) {
increment(node, key);
}
});
};
increment(nodes, key);
return nodes;
};
Can someone help how to update the parent and not increment roots value?
</details>
# 答案1
**得分**: 2
以下是翻译好的部分:
```javascript
function inc(nodes, key, depth = 0) {
for (let n of nodes)
if (n.key === key || inc(n.nodes ?? [], key, depth + 1)) {
if (depth > 0)
n.curr++
return true
}
}
inc(data, 'id7')
这段代码的想法是,如果当前节点已经直接或间接地增加,以便父节点可以相应地进行更新,就返回true
。
英文:
Something like this should work:
function inc(nodes, key, depth = 0) {
for (let n of nodes)
if (n.key === key || inc(n.nodes ?? [], key, depth + 1)) {
if (depth > 0)
n.curr++
return true
}
}
inc(data, 'id7')
The idea is to return true
if the current node has been directly or indirectly incremented so that the parent can update accordingly.
答案2
得分: 2
我认为这段代码会完成任务:
(基于@gog的回答,希望这个解释清楚)
function inc(nodes, key, depth = 0) {
for (let n of nodes) {
const nodeOwnKeyMatches = n.key === key;
const nodeChildsKeyMatches = inc(n.nodes, key, depth + 1);
if (!nodeOwnKeyMatches && !nodeChildsKeyMatches) continue;
if (nodeOwnKeyMatches || depth > 0) n.curr++;
return true;
}
}
const data = [
{
key: "id1",
name: "Category 1",
curr: 0,
total: 0,
nodes: [
{
key: "id2",
name: "Applications",
curr: 20,
total: 30,
nodes: [
{
key: "id3",
name: "Gaming",
curr: 5,
total: 10,
nodes: [],
},
{
key: "id4",
name: "Operating System",
curr: 15,
total: 20,
nodes: [],
},
],
},
],
},
{
key: "id5",
name: "Category 2",
curr: 0,
total: 0,
nodes: [
{
key: "id6",
name: "Sub Category",
curr: 12,
total: 48,
nodes: [
{
key: "id7",
name: "Inside Sub",
curr: 12,
total: 48,
nodes: [],
},
],
},
],
},
{
key: "id8",
name: "Last One",
curr: 0,
total: 0,
nodes: [],
},
];
inc(data, "id4");
console.log(data);
英文:
I think this code will do the job:
(it's based on @gog answer and is self-explanatory hopefully)
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function inc(nodes, key, depth = 0) {
for (let n of nodes) {
const nodeOwnKeyMatches = n.key === key;
const nodeChildsKeyMatches = inc(n.nodes, key, depth + 1);
if (!nodeOwnKeyMatches && !nodeChildsKeyMatches) continue;
if (nodeOwnKeyMatches || depth > 0) n.curr++;
return true;
}
}
const data = [
{
key: "id1",
name: "Category 1",
curr: 0,
total: 0,
nodes: [
{
key: "id2",
name: "Applications",
curr: 20,
total: 30,
nodes: [
{
key: "id3",
name: "Gaming",
curr: 5,
total: 10,
nodes: [],
},
{
key: "id4",
name: "Operating System",
curr: 15,
total: 20,
nodes: [],
},
],
},
],
},
{
key: "id5",
name: "Category 2",
curr: 0,
total: 0,
nodes: [
{
key: "id6",
name: "Sub Category",
curr: 12,
total: 48,
nodes: [
{
key: "id7",
name: "Inside Sub",
curr: 12,
total: 48,
nodes: [],
},
],
},
],
},
{
key: "id8",
name: "Last One",
curr: 0,
total: 0,
nodes: [],
},
];
inc(data, "id4");
console.log(data);
<!-- end snippet -->
答案3
得分: 1
你可以实现一个遍历器来遍历这棵树。
const main = () => {
incrementRecursively(data, 'id4');
console.log(data);
};
const incrementRecursively = (nodeList, key) => {
const childPredicate = (node) => node.key === key;
walkForest(nodeList, (node, parent, depth) => {
const isChild = depth > 0; /* or parent != null */
if (isChild && childMatches(node, childPredicate)) {
node.curr++;
}
});
};
// 后序遍历
const walkTree = (tree, walker, parent = null, depth = 0) => {
if (tree.nodes?.length) {
tree.nodes.forEach(node => walkTree(node, walker, tree, depth + 1));
}
walker(tree, parent, depth);
};
const walkForest = (forest, walker) => {
forest.forEach(tree => walkTree(tree, walker));
};
const childMatches = (node, predicate) =>
predicate(node) || node.nodes.some(child => childMatches(child, predicate));
const data = [{
key: "id1",
name: "Category 1",
curr: 0,
total: 0,
nodes: [{
key: "id2",
name: "Applications",
curr: 20,
total: 30,
nodes: [{
key: "id3",
name: "Gaming",
curr: 5,
total: 10,
nodes: []
}, {
key: "id4",
name: "Operating System",
curr: 15,
total: 20,
nodes: []
}]
}]
},
{
key: "id5",
name: "Category 2",
curr: 0,
total: 0,
nodes: [{
key: "id6",
name: "Sub Category",
curr: 12,
total: 48,
nodes: [{
key: "id7",
name: "Inside Sub",
curr: 12,
total: 48,
nodes: []
}]
}]
},
{
key: "id8",
name: "Last One",
curr: 0,
total: 0,
nodes: []
}
];
main();
.as-console-wrapper { top: 0; max-height: 100% !important; }
英文:
You could implement a walker to step through the tree.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const main = () => {
incrementRecursively(data, 'id4');
console.log(data);
};
const incrementRecursively = (nodeList, key) => {
const childPredicate = (node) => node.key === key;
walkForest(nodeList, (node, parent, depth) => {
const isChild = depth > 0; /* or parent != null */
if (isChild && childMatches(node, childPredicate)) {
node.curr++;
}
});
};
// Post-order
const walkTree = (tree, walker, parent = null, depth = 0) => {
if (tree.nodes?.length) {
tree.nodes.forEach(node => walkTree(node, walker, tree, depth + 1));
}
walker(tree, parent, depth);
};
const walkForest = (forest, walker) => {
forest.forEach(tree => walkTree(tree, walker));
};
const childMatches = (node, predicate) =>
predicate(node) || node.nodes.some(child => childMatches(child, predicate));
const data = [{
key: "id1",
name: "Category 1",
curr: 0,
total: 0,
nodes: [{
key: "id2",
name: "Applications",
curr: 20,
total: 30,
nodes: [{
key: "id3",
name: "Gaming",
curr: 5,
total: 10,
nodes: []
}, {
key: "id4",
name: "Operating System",
curr: 15,
total: 20,
nodes: []
}]
}]
},
{
key: "id5",
name: "Category 2",
curr: 0,
total: 0,
nodes: [{
key: "id6",
name: "Sub Category",
curr: 12,
total: 48,
nodes: [{
key: "id7",
name: "Inside Sub",
curr: 12,
total: 48,
nodes: []
}]
}]
},
{
key: "id8",
name: "Last One",
curr: 0,
total: 0,
nodes: []
}
];
main();
<!-- language: lang-css -->
.as-console-wrapper { top: 0; max-height: 100% !important; }
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论