有没有比这更好的方法来实现 javascript 中的函数式递归 findById?

Is there a better way to implement a functional recursive findById in javascript than this?

我不喜欢循环,但是这似乎很容易用循环解决,但很难使用函数式编程。这是循环版本:

for(var i = 0; i < collection.length; i++) {
    var result = collection[i].findById(id);
    if (result) {
        return result;
    }
}

由于这是一个常见的模式,我希望在 lodash 中找到一个功能性的替代方案。然而,我能想到的最好的是:

return _.first(_.compact(_.map(collection, e => e.findById(id)));

这不仅丑陋,而且它会在第一个 return 真实之后 return 对集合的每个元素调用 findById。

你是如何实现的?

怎么样:

_.find(collection, function(c) {
  return c.findById(id) === true;
});

如果要使用纯javascript:

function findFirstById(collection, id, pos) {
  pos = (typeof pos === 'undefined') ? 0 : pos;
  if (pos >= collection.length)
    return false;
  var result = collection[pos].findById(id);
  if (result)
    return result;
  else
    return findFirstById(collection, id, pos + 1);
}

对你有帮助吗?

呃,也好不了多少,不过我猜你可以用some来实现短路。有点忽略了使用函数式结构使事情更具可读性的要点,但它应该有效...

var result;
collection.some(function(datum){
    return (result = datum.findById(id)) || return result == true;
});

ES7规范中也有find。当您拥有它时,您将能够执行以下操作:

collection.find(function(datum){
    return datum.findById(id) !== null;
});

如果你有这两个功能

let uncurry = f => (x,y) => f(x)(y);
let reduce = f => i => xs => xs.reduce(uncurry(f), i);

你可以写一个简单的findById

let findById = id => reduce(y => x => y || x.findById(id))(null);

这样使用

findById(15)(collection); // => result | null

它仍然会遍历您的 collection 中的每个项目,但它是 short-circuit evaluated 并且只会调用 findById 直到 一个结果找到了。


这是 ES5

var uncurry = function uncurry(f) {
  return function (x, y) {
    return f(x)(y);
  };
};
var reduce = function reduce(f) {
  return function (i) {
    return function (xs) {
      return xs.reduce(uncurry(f), i);
    };
  };
};

var findById = function findById(id) {
  return reduce(function (y) {
    return function (x) {
      return y || x.findById(id);
    };
  })(null);
};

如果你想坚持使用 underscore/lodash,你可以使用这个

let findById = id => xs =>
  _.reduce(xs, (result, x) => result || x.findById(id), null);