对于接受数字数组的函数,如果它包含至少一个偶数,则返回true(否则为false),我有以下2个解。
解决方案1(来自forEach):
var hasEven = function (collection) {
var isEven = false;
collection.forEach(function (entry) {
if (entry % 2 === 0) {
isEven = true;
return;
}
});
return isEven;
}
解决方案2(通过减少):
var hasEven = function (collection) {
return collection.reduce(function (result, entry) {
return (entry % 2 === 0) ? true : result;
}, false);
}
第一个解决方案允许我在找到偶数时立即返回true。另一方面,第二种解决方案提供最短的代码。哪一个更好?
ps - 是的,有更好的解决方案......比如使用array.some(...)。但我特别感兴趣的是比较这里提供的解决方案。是的,现在解决方案正常运行。 :)
答案 0 :(得分:6)
在您编辑的问题中,您已说过:
我对比较此处提供的解决方案特别感兴趣
使用凿子或螺丝刀砸钉子会更好吗?唯一正确的答案是:不要用锤子。
比较两种解决方案,使用错误的工具完成工作最终成为一个意见问题。你喜欢简约吗?转到forEach
。简洁?使用reduce
。我会在代码审查中将其标记为次优选择,并且不会将其视为比另一个更多或更不理想。
我原来的回答:
在这种情况下,都没有。 Array#some
(MDN | spec)将是确定数组是否至少有一个符合条件的条目的合适选择:
var hasEven = function(collection) {
return collection.some(function(entry) {
return entry % 2 === 0;
});
};
一旦回调返回真值, Array#some
就会停止循环。如果回调返回了真值,则some
的返回值为true
,如果没有,则返回false
(所有元素都经过测试且没有匹配)。
或者使用ES2015:
// ES2015 (aka ES6) only
let hasEven = function(collection) {
return collection.some(entry => entry % 2 === 0);
};
或者我们可以得到真正的浓缩(可能以牺牲可读性为代价,但也许不是在我们真正习惯箭头功能时):
// ES2015 (aka ES6) only
let hasEven = collection => collection.some(entry => entry % 2 === 0);
(本节引用the code in your original question。)
我应该注意,您的示例实现都不起作用,forEach
和reduce
都不起作用。 forEach
一个将始终返回false
,因为回调中的return true
只是从回调中返回而根本没有任何效果。 reduce
将导致A)无法测试数组中的第一个条目; B)只告诉你数组中的 last 条目是否是偶数,而不是之前的任何条目是否为;和C)如果在只有一个条目的数组上调用,则返回第一个条目的值,而不是true
或false
。
正确的forEach
看起来像这样(但会不必要地循环):
var hasEven = function(collection) {
var result = false;
collection.forEach(function(entry) {
result = result || entry % 2 === 0;
});
return result;
};
正确的reduce
版本看起来像这样(但会不必要地循环):
var hasEven = function(collection) {
return collection.reduce(function(result, current) {
return result || current % 2 === 0;
}, false);
};
请注意,在上面,我使用了
return entry % 2 === 0;
而不是
return (entry % 2 === 0) ? true : false;
===
的结果是已经一个布尔值。