【问题标题】:Traverse JavaScript array and dynamically find deep nested values遍历 JavaScript 数组并动态查找深层嵌套值
【发布时间】:2020-07-24 22:51:49
【问题描述】:

我目前正在手动循环遍历一个数组并进行越来越深的嵌套循环来比较值,但我很好奇是否有任何方法可以自动执行此搜索?我需要找到深层嵌套数组,比较 1 或 2 个值,然后还可以修改这些值。

示例数组。

searchableArray = [];

searchableArray.push({id: 3, type: 'some-type', text: 'text', nestedElements: [{id: 4, type: 'some-type', text: 'other text', nestedElements: []}, {id: 5, type: 'another-type',  text: 'more text', nestedElements: []}]})
searchableArray.push({id: 6, type: 'other-type', text: 'text', nestedElements: [{id: 7, type: 'other-type', text: 'other text', nestedElements: []}, {id: 8, type: 'another-type',  text: 'more text', nestedElements: []}]})
searchableArray.push({id: 9, type: 'another-type', text: 'text', nestedElements: [{id: 10, type: 'another-type', text: 'other text', nestedElements: []}, {id: 11, type: 'another-type',  text: 'more text', nestedElements: []}]})

基本上我需要搜索 id(它将在整个数组和对象中是唯一的,但可以嵌套在另一个数组内的对象深处的各个级别。但总是称为“nestedElements”。

我需要能够找到 ID,然后修改 ID 所属的对象并将其放回我正在使用的数组中。

现在我只是为每个潜在的嵌套数组制作手动循环。 (这是很多额外的复制粘贴代码)

for(var i = 0; i < searchableArray.length; ++i) 
{
    if(searchableArray[i].id == 6) //6 would actually be a variable, just doing a manual example
    {
        if(searchableArray[i].nestedElements.length > 0)
        {
            for(var j = 0; j < searchableArray[i].nestedElements.length; ++j) 
            {
                if(searchableArray[i].nestedElements[j].id == '7')
                {
                    if(searchableArray[i].nestedElements[j].type == 'other-type')
                    {
                        searchableArray[i].nestedElements[j].dosomething = 'do this to something in the object';
                    }
                    else if(searchableArray[i].nestedElements[j].type == 'another-type')
                    {
                        searchableArray[i].nestedElements[j].dosomething = 'do this other thing to the object';
                    }
                }
            }
        }
    }
}

如果所有内容都使用嵌套循环,这将变得非常庞大,那么有没有更简单的方法来做到这一点?

谢谢!

【问题讨论】:

  • 我建议使用递归来解决这个问题

标签: javascript arrays loops object


【解决方案1】:

这就是你想要的:

const searchableArray = [];

searchableArray.push({ id: 3, type: 'some-type', text: 'text', nestedElements: [{ id: 4, type: 'some-type', text: 'other text', nestedElements: [] }, { id: 5, type: 'another-type', text: 'more text', nestedElements: [] }] })
searchableArray.push({ id: 6, type: 'other-type', text: 'text', nestedElements: [{ id: 7, type: 'other-type', text: 'other text', nestedElements: [] }, { id: 8, type: 'another-type', text: 'more text', nestedElements: [] }] })
searchableArray.push({ id: 9, type: 'another-type', text: 'text', nestedElements: [{ id: 10, type: 'another-type', text: 'other text', nestedElements: [] }, { id: 11, type: 'another-type', text: 'more text', nestedElements: [] }] });

const find = (id, cb) => {
    const ar = searchableArray.slice(0);
    for (var i = 0; i < ar.length; i++) {
        if (ar[i].id === id) {
            return cb(ar[i]);
        }
        if (ar[i].nestedElements.length) {
            ar.push(...ar[i].nestedElements);
        }
    }

}

find(7, (o) => {
    if (o.type == 'other-type') {
        o.dosomething = 'do this to something in the object';
    } else if (o.type == 'another-type') {
        o.dosomething = 'do this other thing to the object';
    }
});

console.log(JSON.stringify(searchableArray));

【讨论】:

    【解决方案2】:

    你可以通过一些代码重构来简化你的结构:

    1. &amp;&amp; 运算符可以避免嵌套 if
    2. 您可以避免使用内部 for 循环并改用 find

    let searchableArray = [];
    
    searchableArray.push({id: 3, type: 'some-type', text: 'text', nestedElements: [{id: 4, type: 'some-type', text: 'other text', nestedElements: []}, {id: 5, type: 'another-type',  text: 'more text', nestedElements: []}]})
    searchableArray.push({id: 6, type: 'other-type', text: 'text', nestedElements: [{id: 7, type: 'other-type', text: 'other text', nestedElements: []}, {id: 8, type: 'another-type',  text: 'more text', nestedElements: []}]})
    searchableArray.push({id: 9, type: 'another-type', text: 'text', nestedElements: [{id: 10, type: 'another-type', text: 'other text', nestedElements: []}, {id: 11, type: 'another-type',  text: 'more text', nestedElements: []}]})
    
    
    searchableArray.forEach(item => {
        if(item.id === 6 && item.nestedElements.length > 0 && item.nestedElements.find(item => item.id === 7 && item.type === "other-type")){
            item.nestedElements.find(item => item.id === 7 && item.type === "other-type").dosomething = 'do this to something in the object';       
        } else if (item.id === 6 && item.nestedElements.length > 0 && item.nestedElements.find(item => item.id === 7 && item.type === "another-type")){
            item.nestedElements.find(item => item.id === 7 && item.type === "another-type").dosomething = 'do this other thing to the object';
        }   
    });
    
    console.log(searchableArray);

    【讨论】:

      【解决方案3】:

      例子:

      searchableArray.forEach(function(el){
                          if (el.hasOwnProperty("nestedElements") && el.nestedElements instanceof Array){
                              el.nestedElements.forEach(function(el1){
                                 if (el1.id===7){
                                     
                                 }
                              });
                          }
                  });
      

      【讨论】:

        【解决方案4】:

        这些天我们尽量不要重新发明太多,为此我建议object-scan。一旦你把头绕在它周围,它就非常强大。以下是您的使用方法:

        // const objectScan = require('object-scan');
        
        const modify = (id, task, data) => objectScan(['**.id'], {
          abort: true,
          rtn: 'bool',
          filterFn: ({ value, parent }) => {
            if (value === id) {
              task(parent);
              return true;
            }
            return false;
          }
        })(data);
        
        const searchableArray = [{ id: 3, type: 'some-type', text: 'text', nestedElements: [{ id: 4, type: 'some-type', text: 'other text', nestedElements: [] }, { id: 5, type: 'another-type', text: 'more text', nestedElements: [] }] }, { id: 6, type: 'other-type', text: 'text', nestedElements: [{ id: 7, type: 'other-type', text: 'other text', nestedElements: [] }, { id: 8, type: 'another-type', text: 'more text', nestedElements: [] }] }, { id: 9, type: 'another-type', text: 'text', nestedElements: [{ id: 10, type: 'another-type', text: 'other text', nestedElements: [] }, { id: 11, type: 'another-type', text: 'more text', nestedElements: [] }] }];
        
        console.log(modify(7, (obj) => {
          if (obj.type === 'other-type') {
            obj.dosomething = 'do this to something in the object';
          } else if (obj.type === 'another-type') {
            obj.dosomething = 'do this other thing to the object';
          }
        }, searchableArray)); // true iff executed
        // => true
        
        console.log(searchableArray);
        // => [ { id: 3, type: 'some-type', text: 'text', nestedElements: [ { id: 4, type: 'some-type', text: 'other text', nestedElements: [] }, { id: 5, type: 'another-type', text: 'more text', nestedElements: [] } ] }, { id: 6, type: 'other-type', text: 'text', nestedElements: [ { id: 7, type: 'other-type', text: 'other text', nestedElements: [], dosomething: 'do this to something in the object' }, { id: 8, type: 'another-type', text: 'more text', nestedElements: [] } ] }, { id: 9, type: 'another-type', text: 'text', nestedElements: [ { id: 10, type: 'another-type', text: 'other text', nestedElements: [] }, { id: 11, type: 'another-type', text: 'more text', nestedElements: [] } ] } ]
        .as-console-wrapper {max-height: 100% !important; top: 0}
        &lt;script src="https://bundle.run/object-scan@13.8.0"&gt;&lt;/script&gt;

        免责声明:我是object-scan的作者

        【讨论】:

          猜你喜欢
          • 2021-07-07
          • 2020-12-10
          • 1970-01-01
          • 1970-01-01
          • 2021-06-16
          • 2020-04-13
          • 1970-01-01
          • 2021-11-05
          • 1970-01-01
          相关资源
          最近更新 更多