【问题标题】:how to update array of objects if it matches while recursively search in JavaScript如果在JavaScript中递归搜索时匹配,如何更新对象数组
【发布时间】:2021-09-16 12:12:40
【问题描述】:

我想在递归搜索找到特定节点后用值更新对象。

我需要在哪里添加逻辑来实现这一点?

我想从嵌套的对象数组中获取第一个找到的对象,并根据迭代使用selected:true 更新数据以获得值showTree: true

功能:

let findDeep = function(data, label) {
  return data.filter(function(e) {
    if (e.label.includes(label)) {
      data.map(el=> el.selected= "true"); // logic to select the first found value
      return e;
    } 
    else if (e.item) 
    //logic for showTree: true
    return findDeep(e.item, label);
  });
};

数据:

let testData = [
  {
    id: 1,
    label: 'parent1',
    item: [
      {
        id: 21,
        label: 'child1',
        item: [
          {
            id: 211,
            label: 'child31',
            item: [
              {
                id: 2111,
                label: 'child2211',
                item: [
                  {
                    id: 21111,
                    label: 'child22111'
                  }
                ]
              }
            ]
          },
          {
            id: 222,
            label: 'child32'
          }
        ]
      },
      {
        id: 22,
        label: 'child2',
        item: [
          {
            id: 221,
            label: 'child421',
            item: [
              {
                id: 2211,
                label: 'child2211'
              }
            ]
          },
          {
            id: 222,
            label: 'child222'
          }
        ]
      }
    ]
  },
  {
    id: 2,
    label: 'parent2',
    item: [
      {
        id: 21,
        label: 'child2',
        item: [
          {
            id: 511,
            label: 'child51',
            item: [
              {
                id: 5111,
                label: 'child5211',
                item: [
                  {
                    id: 51111,
                    label: 'child52111'
                  }
                ]
              }
            ]
          },
          {
            id: 522,
            label: 'child352'
          }
        ]
      }
    ]
  }
];

我想在输出中实现一些东西

console.log(findDeep(testData, 'child3')[0]);

//output list
[
   {
      "id":1,
      "label":"parent1",
      "showTree": true,
      "item":[
         {
            "id":21,
            "label":"child1",
            "showTree": true,
            "item":[
               {
                  "id":211,
                  "label":"child31",
                  "selected" true,
                  "item":[
                     {
                        "id":2111,
                        "label":"child2211",
                        "item":[
                           {
                              "id":21111,
                              "label":"child22111"
                           }
                        ]
                     }
                  ]
               },
               {
                  "id":222,
                  "label":"child32"
               }
            ]
         },
         {
            "id":22,
            "label":"child2",
            "item":[
               {
                  "id":221,
                  "label":"child421",
                  "item":[
                     {
                        "id":2211,
                        "label":"child2211"
                     }
                  ]
               },
               {
                  "id":222,
                  "label":"child222"
               }
            ]
         }
      ]
   },
   {
      "id":2,
      "label":"parent2",
      "item":[
         {
            "id":21,
            "label":"child2",
            "item":[
               {
                  "id":511,
                  "label":"child51",
                  "item":[
                     {
                        "id":5111,
                        "label":"child5211",
                        "item":[
                           {
                              "id":51111,
                              "label":"child52111"
                           }
                        ]
                     }
                  ]
               },
               {
                  "id":522,
                  "label":"child352"
               }
            ]
         }
      ]
   }
]

//ouptput selected value

{
   "id":211,
   "label":"child31",
   "selected":true,
   "item":[
      {
         "id":2111,
         "label":"child2211",
         "item":[
            {
               "id":21111,
               "label":"child22111"
            }
         ]
      }
   ]
}

【问题讨论】:

  • 您的目标节点是child31,但您的函数调用是child3。这是一个错字还是你真的想在这里使用字符串或子字符串逻辑的前缀?
  • @ggorlen 不,我想使用“包含”逻辑,以便选择第一个搜索词

标签: javascript recursion tree


【解决方案1】:

您可以执行normal tree search,修改找到的属性,然后将true 向后传递到树的根,同时应用showTree: true

请注意,这是一种就地方法,因此语义与您在通话中显示的略有不同。这可能最适合像这样的算法,它只是修改现有结构上的一些属性,而不是从头开始重新分配整个事物。返回原地算法的原始结构是一种反模式,就像 .sort().reverse() 出于链接的目的所做的那样——这可能会导致令人惊讶和微妙的错误。

const expandPath = (nodes, targetLabel) => {
  for (const node of nodes || []) {
    if (node.label.includes(targetLabel)) {
      return node.selected = true;
    }
    else if (expandPath(node.item, targetLabel)) {
      return node.showTree = true;
    }
  }
};

const testData = [ { id: 1, label: 'parent1', item: [ { id: 21, label: 'child1', item: [ { id: 211, label: 'child31', item: [ { id: 2111, label: 'child2211', item: [ { id: 21111, label: 'child22111' } ] } ] }, { id: 222, label: 'child32' } ] }, { id: 22, label: 'child2', item: [ { id: 221, label: 'child421', item: [ { id: 2211, label: 'child2211' } ] }, { id: 222, label: 'child222' } ] } ] }, { id: 2, label: 'parent2', item: [ { id: 21, label: 'child2', item: [ { id: 511, label: 'child51', item: [ { id: 5111, label: 'child5211', item: [ { id: 51111, label: 'child52111' } ] } ] }, { id: 522, label: 'child352' } ] } ] } ];

expandPath(testData, "child3");
console.log(testData[0]);

请注意,添加的属性位于每个节点的底部。

另外,在您最初的尝试中,请避免使用map 进行就地操作——其目的是分配一个新数组,而不是修改它。请改用forEach

【讨论】:

  • 只有一个问题...有什么方法可以得到我想要显示的出现次数示例:“1 of 20 matches”
  • expandPath(testData, 'child421');当我通过它时,它显示节点不可迭代
  • 对,我看到叶节点没有.item。更新。回复:所有匹配项,您是否想要计算为特定呼叫添加了多少“selected:true”键?您可以进行单独的传递,通常的树搜索返回具有该属性的节点数。它可以通过返回一个计数而不是 true/flase 来合并为一个。
  • 其实我想要一个功能,用户可以在其中查看下一个搜索记录和以前的搜索记录。
  • 好的,感谢您提出一个新问题,我来看看——我没有意识到您想要选择超过 1 个项目。我展示的当前算法只是扩展它找到的第一个匹配项,然后停止。
【解决方案2】:

我建议使用字符串方法,例如

- `includes` or
- `startsWith`

连同想要的参数。

search = (array, type, value) => array.some(o => {
    if (o.label[type](value)) return o.selected = true;
    return search(o.item || [], type, value);
})

【讨论】:

  • 非常感谢,Nina,只有一个问题.. 如何根据所选值更新树?如果我需要进行迭代以达到所选值,我想使 showTree: true
  • [{"id":1,"label":"parent1","showTree":true,"item":[{"id":21,"label":"child1", "showTree":true,"item":[{"id":211,"label":"child31","item":[{"id":2111,"label":"child2211","item": [{"id":21111,"label":"child22111"}]}]},{"id":222,"label":"child32"}],"selected":true},{"id": 22,"label":"child2","item":[{"id":221,"label":"child421","item":[{"id":2211,"label":"child2211"} ]},{"id":222,"label":"child222"}]}]},{"id":2,"label":"parent2","item":[{"id":21, "label":"child2","item":[{"id":511,"label":"child51","item":[{"id":5111,"label":"child5211","item ":[]}]},{"id":522,"label":"child352"}]}]}]
猜你喜欢
  • 2016-05-05
  • 1970-01-01
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多