我不喜欢循环,但是这似乎很容易通过循环和使用函数式编程来解决。这是循环版本:
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)));
这不仅是丑陋的,而且在第一个元素返回真实之后它会返回时,会在集合的每个元素上调用findById。
你是如何实现这个的?
答案 0 :(得分:1)
如果你有这两个功能
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
它仍然会迭代收藏中的每个项目,但它是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);
};
如果你想坚持使用下划线/ lodash,你可以使用这个
let findById = id => xs =>
_.reduce(xs, (result, x) => result || x.findById(id), null);
答案 1 :(得分:0)
怎么样:
_.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);
}
这对你有帮助吗?
答案 2 :(得分:0)
呃,它好多了,但我想你可以用some
来实现短路。 Kinda错过了使用功能结构使事物更具可读性的观点,但它应该有用......
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;
});