【问题标题】:Find value in javascript array of objects deeply nested with ES6在 ES6 深度嵌套的对象的 javascript 数组中查找值
【发布时间】:2018-03-01 22:45:07
【问题描述】:

在一个对象数组中,我需要找到一个 value -- 其中 keyactivity :但是 activity key 可以像这样深入嵌套在数组中:

const activityItems = [
    {
        name: 'Sunday',
        items: [
            {
                name: 'Gym',
                activity: 'weights',
            },
        ],
    },
    {
        name: 'Monday',
        items: [
            {
                name: 'Track',
                activity: 'race',
            },
            {
                name: 'Work',
                activity: 'meeting',
            },
            {
                name: 'Swim',
                items: [
                    {
                        name: 'Beach',
                        activity: 'scuba diving',
                    },
                    {
                        name: 'Pool',
                        activity: 'back stroke',
                    },
                ],
            },
        ],    
    },
    {} ...
    {} ...
];

所以我写了一个递归算法来找出某个活动是否在数组中:

let match = false;
const findMatchRecursion = (activity, activityItems) => {
    for (let i = 0; i < activityItems.length; i += 1) {
        if (activityItems[i].activity === activity) {
            match = true;
            break;
        }

        if (activityItems[i].items) {
            findMatchRecursion(activity, activityItems[i].items);
        }
    }

    return match;
};

是否有ES6 方法来确定活动是否存在于这样的数组中?

我尝试过这样的事情:

const findMatch(activity, activityItems) {
    let obj = activityItems.find(o => o.items.activity === activity);
    return obj;
}

但这不适用于深度嵌套的活动。

谢谢

【问题讨论】:

    标签: javascript arrays algorithm es6-modules


    【解决方案1】:

    您可以使用some() 方法和递归来查找活动是否存在于任何级别并返回真/假作为结果。

    const activityItems = [{"name":"Sunday","items":[{"name":"Gym","activity":"weights"}]},{"name":"Monday","items":[{"name":"Track","activity":"race"},{"name":"Work","activity":"meeting"},{"name":"Swim","items":[{"name":"Beach","activity":"scuba diving"},{"name":"Pool","activity":"back stroke"}]}]}]
    
    let findDeep = function(data, activity) {
      return data.some(function(e) {
        if(e.activity == activity) return true;
        else if(e.items) return findDeep(e.items, activity)
      })
    }
    
    console.log(findDeep(activityItems, 'scuba diving'))

    【讨论】:

      【解决方案2】:

      首先,一旦通过递归调用找到匹配项,就可以通过暂停来改进您的功能。此外,您既要在外面声明match,也要返回它。可能会更好地返回。

      const findMatchRecursion = (activity, activityItems) => {
          for (let i = 0; i < activityItems.length; i += 1) {
              if (activityItems[i].activity === activity) {
                  return true;
              }
      
              if (activityItems[i].items && findMatchRecursion(activity, activityItems[i].items) {
                  return true;
              }
          }
      
          return false;
      };
      

      没有内置的深度搜索,但如果您愿意,可以将 .find 与命名函数一起使用。

      var result = !!activityItems.find(function fn(item) {
        return item.activity === "Gym" || (item.items && item.items.find(fn));
      });
      

      【讨论】:

      • 除非我遗漏了什么,否则这将返回包含搜索对象的最顶层父级,而不是对象本身。
      【解决方案3】:

      虽然不如递归算法优雅,但您可以 JSON.stringify() 数组,它给出了:

      [{"name":"Sunday","items":[{"name":"Gym","activity":"weights"}]},{"name":"Monday","items":[{"name":"Track","activity":"race"},{"name":"Work","activity":"meeting"},{"name":"Swim","items":[{"name":"Beach","activity":"scuba diving"},{"name":"Pool","activity":"back stroke"}]}]}]
      

      然后您可以使用template literal 来搜索模式:

      `"activity":"${activity}"`
      

      功能齐全:

      findMatch = (activity, activityItems) =>
        JSON.stringify(activityItems).includes(`"activity":"${activity}"`);
      

      const activityItems = [{
          name: 'Sunday',
          items: [{
            name: 'Gym',
            activity: 'weights',
          }, ],
        },
        {
          name: 'Monday',
          items: [{
              name: 'Track',
              activity: 'race',
            },
            {
              name: 'Work',
              activity: 'meeting',
            },
            {
              name: 'Swim',
              items: [{
                  name: 'Beach',
                  activity: 'scuba diving',
                },
                {
                  name: 'Pool',
                  activity: 'back stroke',
                },
              ],
            },
          ],
        }
      ];
      
      findMatch = (activity, activityItems) =>
        JSON.stringify(activityItems).includes(`"activity":"${activity}"`);
      
      console.log(findMatch('scuba diving', activityItems)); //true
      console.log(findMatch('dumpster diving', activityItems)); //false

      【讨论】:

        【解决方案4】:

        我们现在使用object-scan 来处理像这样的简单数据处理任务。一旦您了解如何使用它,它真的很棒。以下是如何回答您的问题

        // const objectScan = require('object-scan');
        
        const find = (activity, input) => objectScan(['**'], {
          abort: true,
          rtn: 'value',
          filterFn: ({ value }) => value.activity === activity
        })(input);
        
        const activityItems = [{"name":"Sunday","items":[{"name":"Gym","activity":"weights"}]},{"name":"Monday","items":[{"name":"Track","activity":"race"},{"name":"Work","activity":"meeting"},{"name":"Swim","items":[{"name":"Beach","activity":"scuba diving"},{"name":"Pool","activity":"back stroke"}]}]}]
        
        console.log(find('scuba diving', activityItems));
        // => { name: 'Beach', activity: 'scuba diving' }
        .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的作者

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-02-14
          • 1970-01-01
          • 1970-01-01
          • 2019-08-10
          • 1970-01-01
          • 2018-01-02
          • 2020-12-10
          • 2017-06-29
          相关资源
          最近更新 更多