【问题标题】:Get first element of a collection that matches iterator function获取与迭代器函数匹配的集合的第一个元素
【发布时间】:2013-10-30 02:53:42
【问题描述】:

我想用_.filter 实现类似_.first 的东西,也就是说,拥有一组元素,我想获得第一个(如果存在)与真值测试(迭代器)匹配的元素。

例如,给定如下数组:

var arr = [{a: 1}, {a: 5}, {a: 9}, {a: 11}, {a: 15}]

我想获得第一个(也是唯一一个)与我的自定义函数匹配的元素:

_.filterFirst(arr, function(el) { return el.a > 10; }); // make it

到目前为止:

_.first(arr) == {a:1}
_.filter(arr, function(...)) == [{a:11}, {a:15}]

有没有比_.first(_.filter(arr, iterator))更好的干净解决方案?

【问题讨论】:

  • 看一下查找功能underscorejs.org/#find
  • 为什么不只是 _.filter(arr, iterator)[0]
  • @levi 因为它消耗的 CPU 超出了应有的水平。
  • 为什么不只是 _.filter(arr, iterator)[0]
  • @RobertRavikumar 你听说过性能吗?还是算法复杂度? Here你去。顺便说一句,这个问题已经 5 岁了

标签: javascript collections functional-programming underscore.js


【解决方案1】:

添加标准的 JavaScript Array.prototype.find 方法,因为只是旧的答案会让新手不了解:

const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10);
console.log(found); 
// expected output: 12

示例来自上面链接的 MDN 页面。 还有一个 Array.prototype.findIndex 方法返回谓词产生 true 的位置的索引,而不是该索引的数组元素。

这些方法在 ES2015 中,即。 5 岁,几乎可以在人们使用的所有浏览器中使用,请参阅caniuse link

【讨论】:

    【解决方案2】:

    _.find - 在lodash中: https://lodash.com/docs/4.17.10#find

    var users = [
      { 'user': 'barney',  'age': 36, 'active': true },
      { 'user': 'fred',    'age': 40, 'active': false },
      { 'user': 'pebbles', 'age': 1,  'active': true }
    ];
    
    _.find(users, function(o) { return o.age < 40; });
    // => object for 'barney'
    
    // The `_.matches` iteratee shorthand.
    _.find(users, { 'age': 1, 'active': true });
    // => object for 'pebbles'
    
    // The `_.matchesProperty` iteratee shorthand.
    _.find(users, ['active', false]);
    // => object for 'fred'
    
    // The `_.property` iteratee shorthand.
    _.find(users, 'active');
    // => object for 'barney'
    

    【讨论】:

      【解决方案3】:

      “_.find”是一个很好的解决方案。

      另一种可能更快的解决方案是以这种方式使用“Array.prototype.every”:

      var match;
      arr.every(function(x) { if (x.a > 10) { match = x; return false;} return true; })
      

      【讨论】:

        【解决方案4】:

        你可以使用find:

        查看列表中的每个值,返回第一个 通过真值测试(迭代器),如果没有值通过,则为 undefined 测试。该函数在找到可接受的元素后立即返回, 并且不会遍历整个列表。

        用你的例子:

        var g = _.find(arr, function (x) { return x.a > 10 })
        

        查看主页:http://underscorejs.org

        另一件需要注意的事情(这可能是您的问题)是 chain 将呼叫连接在一起的函数:

        var g = _.chain(arr).filter(function (x) { return x.a > 10 }).first().value()
        

        注意对 filter 和 `first' 的调用,它们可以相互跟随而没有任何嵌套。

        【讨论】:

        • 没错! _.find 是我需要的!
        • ...或 Array.prototype.find(),但 IE 不支持。不过可以使用 polyfill。请注意,仅仅将 ES2015+ 翻译成 ES5 是不够的。
        猜你喜欢
        • 2016-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-08
        • 2017-03-11
        • 2012-01-04
        相关资源
        最近更新 更多