递归根据传递的键更新父子信息

huangapple go评论114阅读模式
英文:

Recursively update parent child info based on key passed

问题

以下是您提供的代码和说明的翻译:

  1. 我有一个看起来像这样的对象数组
  2. const data = [
  3. {
  4. key: "id1",
  5. name: "Category 1",
  6. curr: 0,
  7. total: 0,
  8. nodes: [
  9. {
  10. key: "id2",
  11. name: "Applications",
  12. curr: 20,
  13. total: 30,
  14. nodes: [
  15. {
  16. key: "id3",
  17. name: "Gaming",
  18. curr: 5,
  19. total: 10,
  20. nodes: []
  21. },
  22. {
  23. key: "id4",
  24. name: "Operating System",
  25. curr: 15,
  26. total: 20,
  27. nodes: []
  28. }
  29. ]
  30. }
  31. ]
  32. },
  33. {
  34. key: "id5",
  35. name: "Category 2",
  36. curr: 0,
  37. total: 0,
  38. nodes: [
  39. {
  40. key: "id6",
  41. name: "Sub Category",
  42. curr: 12,
  43. total: 48,
  44. nodes: [
  45. {
  46. key: "id7",
  47. name: "Inside Sub",
  48. curr: 12,
  49. total: 48,
  50. nodes: []
  51. }
  52. ]
  53. }
  54. ]
  55. },
  56. {
  57. key: "id8",
  58. name: "Last One",
  59. curr: 0,
  60. total: 0,
  61. nodes: []
  62. }
  63. ];

每个级别的 key 属性在整个树中都是唯一的。当我将键和此数组传递给一个函数时,它应该递增匹配键级别的 curr 值,此递增应该一直延伸到级别 1。请注意,不应更新级别 0 的项目。所以基本上当我传递 incrementRecursively(data, "id4") 时,输出应该如下所示,

  1. const output = [
  2. {
  3. key: "id1",
  4. name: "Category 1",
  5. curr: 0,
  6. total: 0,
  7. nodes: [
  8. {
  9. key: "id2",
  10. name: "Applications",
  11. curr: 21,
  12. total: 30,
  13. nodes: [
  14. {
  15. key: "id3",
  16. name: "Gaming",
  17. curr: 5,
  18. total: 10,
  19. nodes: []
  20. },
  21. {
  22. key: "id4",
  23. name: "Operating System",
  24. curr: 16,
  25. total: 20,
  26. nodes: []
  27. }
  28. ]
  29. }
  30. ]
  31. },
  32. {
  33. key: "id5",
  34. name: "Category 2",
  35. curr: 0,
  36. total: 0,
  37. nodes: [
  38. {
  39. key: "id6",
  40. name: "Sub Category",
  41. curr: 12,
  42. total: 48,
  43. nodes: [
  44. {
  45. key: "id7",
  46. name: "Inside Sub",
  47. curr: 12,
  48. total: 48,
  49. nodes: []
  50. }
  51. ]
  52. }
  53. ]
  54. },
  55. {
  56. key: "id8",
  57. name: "Last One",
  58. curr: 0,
  59. total: 0,
  60. nodes: []
  61. }
  62. ];

我尝试的代码如下,

  1. const incrementRecursively = (nodes, key) => {
  2. const increment = (nodes, key) => {
  3. nodes.forEach((node) => {
  4. if (node.key === key) {
  5. node.curr++;
  6. }
  7. if (node.nodes.length) {
  8. increment(node.nodes, key);
  9. }
  10. });
  11. };
  12. increment(nodes, key);
  13. return nodes;
  14. };

有人能帮助我如何更新父级而不递增根值吗?

  1. 如果您需要更多帮助或有其他问题,请随时提出。
  2. <details>
  3. <summary>英文:</summary>
  4. 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: []
}
];

  1. `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, &quot;id4&quot;)`, 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: []
}
];

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

  1. Can someone help how to update the parent and not increment roots value?
  2. </details>
  3. # 答案1
  4. **得分**: 2
  5. 以下是翻译好的部分:
  6. ```javascript
  7. function inc(nodes, key, depth = 0) {
  8. for (let n of nodes)
  9. if (n.key === key || inc(n.nodes ?? [], key, depth + 1)) {
  10. if (depth > 0)
  11. n.curr++
  12. return true
  13. }
  14. }
  15. inc(data, 'id7')

这段代码的想法是,如果当前节点已经直接或间接地增加,以便父节点可以相应地进行更新,就返回true

英文:

Something like this should work:

  1. function inc(nodes, key, depth = 0) {
  2. for (let n of nodes)
  3. if (n.key === key || inc(n.nodes ?? [], key, depth + 1)) {
  4. if (depth &gt; 0)
  5. n.curr++
  6. return true
  7. }
  8. }
  9. inc(data, &#39;id7&#39;)

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的回答,希望这个解释清楚)

  1. function inc(nodes, key, depth = 0) {
  2. for (let n of nodes) {
  3. const nodeOwnKeyMatches = n.key === key;
  4. const nodeChildsKeyMatches = inc(n.nodes, key, depth + 1);
  5. if (!nodeOwnKeyMatches && !nodeChildsKeyMatches) continue;
  6. if (nodeOwnKeyMatches || depth > 0) n.curr++;
  7. return true;
  8. }
  9. }
  10. const data = [
  11. {
  12. key: "id1",
  13. name: "Category 1",
  14. curr: 0,
  15. total: 0,
  16. nodes: [
  17. {
  18. key: "id2",
  19. name: "Applications",
  20. curr: 20,
  21. total: 30,
  22. nodes: [
  23. {
  24. key: "id3",
  25. name: "Gaming",
  26. curr: 5,
  27. total: 10,
  28. nodes: [],
  29. },
  30. {
  31. key: "id4",
  32. name: "Operating System",
  33. curr: 15,
  34. total: 20,
  35. nodes: [],
  36. },
  37. ],
  38. },
  39. ],
  40. },
  41. {
  42. key: "id5",
  43. name: "Category 2",
  44. curr: 0,
  45. total: 0,
  46. nodes: [
  47. {
  48. key: "id6",
  49. name: "Sub Category",
  50. curr: 12,
  51. total: 48,
  52. nodes: [
  53. {
  54. key: "id7",
  55. name: "Inside Sub",
  56. curr: 12,
  57. total: 48,
  58. nodes: [],
  59. },
  60. ],
  61. },
  62. ],
  63. },
  64. {
  65. key: "id8",
  66. name: "Last One",
  67. curr: 0,
  68. total: 0,
  69. nodes: [],
  70. },
  71. ];
  72. inc(data, "id4");
  73. 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 -->

  1. function inc(nodes, key, depth = 0) {
  2. for (let n of nodes) {
  3. const nodeOwnKeyMatches = n.key === key;
  4. const nodeChildsKeyMatches = inc(n.nodes, key, depth + 1);
  5. if (!nodeOwnKeyMatches &amp;&amp; !nodeChildsKeyMatches) continue;
  6. if (nodeOwnKeyMatches || depth &gt; 0) n.curr++;
  7. return true;
  8. }
  9. }
  10. const data = [
  11. {
  12. key: &quot;id1&quot;,
  13. name: &quot;Category 1&quot;,
  14. curr: 0,
  15. total: 0,
  16. nodes: [
  17. {
  18. key: &quot;id2&quot;,
  19. name: &quot;Applications&quot;,
  20. curr: 20,
  21. total: 30,
  22. nodes: [
  23. {
  24. key: &quot;id3&quot;,
  25. name: &quot;Gaming&quot;,
  26. curr: 5,
  27. total: 10,
  28. nodes: [],
  29. },
  30. {
  31. key: &quot;id4&quot;,
  32. name: &quot;Operating System&quot;,
  33. curr: 15,
  34. total: 20,
  35. nodes: [],
  36. },
  37. ],
  38. },
  39. ],
  40. },
  41. {
  42. key: &quot;id5&quot;,
  43. name: &quot;Category 2&quot;,
  44. curr: 0,
  45. total: 0,
  46. nodes: [
  47. {
  48. key: &quot;id6&quot;,
  49. name: &quot;Sub Category&quot;,
  50. curr: 12,
  51. total: 48,
  52. nodes: [
  53. {
  54. key: &quot;id7&quot;,
  55. name: &quot;Inside Sub&quot;,
  56. curr: 12,
  57. total: 48,
  58. nodes: [],
  59. },
  60. ],
  61. },
  62. ],
  63. },
  64. {
  65. key: &quot;id8&quot;,
  66. name: &quot;Last One&quot;,
  67. curr: 0,
  68. total: 0,
  69. nodes: [],
  70. },
  71. ];
  72. inc(data, &quot;id4&quot;);
  73. console.log(data);

<!-- end snippet -->

答案3

得分: 1

你可以实现一个遍历器来遍历这棵树。

  1. const main = () => {
  2. incrementRecursively(data, 'id4');
  3. console.log(data);
  4. };
  5. const incrementRecursively = (nodeList, key) => {
  6. const childPredicate = (node) => node.key === key;
  7. walkForest(nodeList, (node, parent, depth) => {
  8. const isChild = depth > 0; /* or parent != null */
  9. if (isChild && childMatches(node, childPredicate)) {
  10. node.curr++;
  11. }
  12. });
  13. };
  14. // 后序遍历
  15. const walkTree = (tree, walker, parent = null, depth = 0) => {
  16. if (tree.nodes?.length) {
  17. tree.nodes.forEach(node => walkTree(node, walker, tree, depth + 1));
  18. }
  19. walker(tree, parent, depth);
  20. };
  21. const walkForest = (forest, walker) => {
  22. forest.forEach(tree => walkTree(tree, walker));
  23. };
  24. const childMatches = (node, predicate) =>
  25. predicate(node) || node.nodes.some(child => childMatches(child, predicate));
  26. const data = [{
  27. key: "id1",
  28. name: "Category 1",
  29. curr: 0,
  30. total: 0,
  31. nodes: [{
  32. key: "id2",
  33. name: "Applications",
  34. curr: 20,
  35. total: 30,
  36. nodes: [{
  37. key: "id3",
  38. name: "Gaming",
  39. curr: 5,
  40. total: 10,
  41. nodes: []
  42. }, {
  43. key: "id4",
  44. name: "Operating System",
  45. curr: 15,
  46. total: 20,
  47. nodes: []
  48. }]
  49. }]
  50. },
  51. {
  52. key: "id5",
  53. name: "Category 2",
  54. curr: 0,
  55. total: 0,
  56. nodes: [{
  57. key: "id6",
  58. name: "Sub Category",
  59. curr: 12,
  60. total: 48,
  61. nodes: [{
  62. key: "id7",
  63. name: "Inside Sub",
  64. curr: 12,
  65. total: 48,
  66. nodes: []
  67. }]
  68. }]
  69. },
  70. {
  71. key: "id8",
  72. name: "Last One",
  73. curr: 0,
  74. total: 0,
  75. nodes: []
  76. }
  77. ];
  78. main();
  1. .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 -->

  1. const main = () =&gt; {
  2. incrementRecursively(data, &#39;id4&#39;);
  3. console.log(data);
  4. };
  5. const incrementRecursively = (nodeList, key) =&gt; {
  6. const childPredicate = (node) =&gt; node.key === key;
  7. walkForest(nodeList, (node, parent, depth) =&gt; {
  8. const isChild = depth &gt; 0; /* or parent != null */
  9. if (isChild &amp;&amp; childMatches(node, childPredicate)) {
  10. node.curr++;
  11. }
  12. });
  13. };
  14. // Post-order
  15. const walkTree = (tree, walker, parent = null, depth = 0) =&gt; {
  16. if (tree.nodes?.length) {
  17. tree.nodes.forEach(node =&gt; walkTree(node, walker, tree, depth + 1));
  18. }
  19. walker(tree, parent, depth);
  20. };
  21. const walkForest = (forest, walker) =&gt; {
  22. forest.forEach(tree =&gt; walkTree(tree, walker));
  23. };
  24. const childMatches = (node, predicate) =&gt;
  25. predicate(node) || node.nodes.some(child =&gt; childMatches(child, predicate));
  26. const data = [{
  27. key: &quot;id1&quot;,
  28. name: &quot;Category 1&quot;,
  29. curr: 0,
  30. total: 0,
  31. nodes: [{
  32. key: &quot;id2&quot;,
  33. name: &quot;Applications&quot;,
  34. curr: 20,
  35. total: 30,
  36. nodes: [{
  37. key: &quot;id3&quot;,
  38. name: &quot;Gaming&quot;,
  39. curr: 5,
  40. total: 10,
  41. nodes: []
  42. }, {
  43. key: &quot;id4&quot;,
  44. name: &quot;Operating System&quot;,
  45. curr: 15,
  46. total: 20,
  47. nodes: []
  48. }]
  49. }]
  50. },
  51. {
  52. key: &quot;id5&quot;,
  53. name: &quot;Category 2&quot;,
  54. curr: 0,
  55. total: 0,
  56. nodes: [{
  57. key: &quot;id6&quot;,
  58. name: &quot;Sub Category&quot;,
  59. curr: 12,
  60. total: 48,
  61. nodes: [{
  62. key: &quot;id7&quot;,
  63. name: &quot;Inside Sub&quot;,
  64. curr: 12,
  65. total: 48,
  66. nodes: []
  67. }]
  68. }]
  69. },
  70. {
  71. key: &quot;id8&quot;,
  72. name: &quot;Last One&quot;,
  73. curr: 0,
  74. total: 0,
  75. nodes: []
  76. }
  77. ];
  78. main();

<!-- language: lang-css -->

  1. .as-console-wrapper { top: 0; max-height: 100% !important; }

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月22日 21:03:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76306504.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定