【问题标题】:Find object by match property in nested array通过嵌套数组中的匹配属性查找对象
【发布时间】:2015-05-07 17:02:00
【问题描述】:

当我的条件涉及嵌套数组时,我没有看到find 对象的方法。

var modules = [{
    name: 'Module1',
    submodules: [{
        name: 'Submodule1',
        id: 1
      }, {
        name: 'Submodule2',
        id: 2
      }
    ]
  }, {
    name: 'Module2',
    submodules: [{
        name: 'Submodule1',
        id: 3
      }, {
        name: 'Submodule2',
        id: 4
      }
    ]
  }
];

这不起作用,因为submodules 是一个数组,而不是一个对象。有没有任何速记可以使这项工作?我试图避免手动迭代数组。

_.where(modules, {submodules:{id:3}});

【问题讨论】:

    标签: lodash


    【解决方案1】:

    Lodash 允许您像这样过滤嵌套数据(包括数组):

    _.filter(modules, { submodules: [ { id: 2 } ]});

    【讨论】:

    • 您也可以使用与_.find 完全相同的语法。
    • @DevonSams 尽管_.filter 返回过滤后的数组或空数组,_.find 返回匹配的元素,可以是对象、数组、数字、字符串、布尔值或未定义。
    • 有没有办法只返回嵌套对象而不是整个父对象?
    • 我怎样才能将一个对象定位在一个条码数组中,该条码数组在一个sizes数组中,而sizes数组在一个colors数组中...我怎样才能直接指向条码?
    【解决方案2】:

    这是我想出的:

    _.find(modules, _.flow(
        _.property('submodules'),
        _.partialRight(_.some, { id: 2 })
    ));
    // → { name: 'Module1', ... }
    

    使用flow(),您可以构造一个回调函数来满足您的需求。调用时,数据流动通过每个函数。您首先需要的是submodules 属性,您可以使用property() 函数获得它。

    然后将子模块数组输入some(),如果它包含您所追求的子模块,则返回true,在本例中为ID 2

    如果您要查找多个模块,而不仅仅是找到的第一个模块,请将 find() 替换为 filter()

    【讨论】:

    • 我喜欢,谢谢!不像动态路径那样优雅,但 lodash 不支持。也许我会做一个混合...
    • 仅供参考,在 Lodash 4.0 中,他们删除了 .any() 函数。现在你可以使用 .some()。
    【解决方案3】:

    我认为你最好的机会是使用一个函数来获取模块。

    _.select(modules, function (module) {
      return _.any(module.submodules, function (submodule) {
        return _.where(submodule, {id:3});
      });
    });
    

    试试这个来获取子模块

    .where(.pluck(modules, "submodules"), {submodules:{id:3}});

    【讨论】:

    • 好主意。我还必须使用_flatten,因为_.pluck 返回一个数组数组。
    • (是的,后来我想到了扁平化),但我完全改变了我的答案,因为它不起作用。充满希望的想法:)
    • 但它确实奏效了。使用 flatten+pluck 逻辑,我的测试有效。 jsbin.com/howazulexe/1/edit?js
    • 我认为目的是获取父模块,而不是子模块。在那种情况下,是的:D
    • 哦,好主意。不是我的情况,但这是一个同样有用的用例。如果您想同时更新您的答案,我会将其标记为已接受。我没有看到任何更清洁的东西。老实说,我很惊讶没有匹配器支持。
    【解决方案4】:

    我对此进行了研究,我认为最好的选择是使用Deepdash。它是进行深度过滤、查找等方法的集合。

    当然可以单独使用 lodash,但使用 Deepdash 会更容易。

    我尝试将以前的答案转换为最新的 Lodash 版本,但这不起作用。在 Lodash v4 中,每种方法都被弃用了。可能的替换:select = map 或 filter,any = some,where = filter)

    findDeep 将带有一些信息的对象返回给找到的项目(只是一些值,有关更多详细信息,请参阅docs):

    • value 是找到的对象
    • key 这是嵌套数组中的索引
    • parent 值的父级

    所以findDeep 的代码如下:

    const modules = [{
      name: 'Module1',
      submodules: [{
        name: 'Submodule1',
        id: 1
      }, {
        name: 'Submodule2',
        id: 2
      }]
    }, {
      name: 'Module2',
      submodules: [{
        name: 'Submodule1',
        id: 3
      }, {
        name: 'Submodule2',
        id: 4
      }]
    }];
    
    const getModule = (modules, id) =>
      _.findDeep(modules, module => module.id === id, {
        childrenPath: "submodules"
      });
    
    
    const resultEl = document.getElementById("result");
    const foundModule = getModule(modules, 3).value;
    
    resultEl.innerText = JSON.stringify(foundModule, null, 2);
    <script src="https://cdn.jsdelivr.net/npm/deepdash/browser/deepdash.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash/lodash.min.js"></script>
    <script>
      deepdash(_);
    </script>
    
    <h2>Example to get module with id = 3</h2>
    <pre id="result"></pre>

    【讨论】:

      猜你喜欢
      • 2019-08-29
      • 2020-06-20
      • 1970-01-01
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      • 2018-01-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多