JavaScript:这里有哪种更好的方法... forEach还是reduce?

时间:2016-02-15 07:40:15

标签: javascript arrays

对于接受数字数组的函数,如果它包含至少一个偶数,则返回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(...)。但我特别感兴趣的是比较这里提供的解决方案。是的,现在解决方案正常运行。 :)

1 个答案:

答案 0 :(得分:6)

在您编辑的问题中,您已说过:

  

我对比较此处提供的解决方案特别感兴趣

使用凿子或螺丝刀砸钉子会更好吗?唯一正确的答案是:不要用锤子。

比较两种解决方案,使用错误的工具完成工作最终成为一个意见问题。你喜欢简约吗?转到forEach。简洁?使用reduce。我会在代码审查中将其标记为次优选择,并且不会将其视为比另一个更多或更不理想。

我原来的回答:

在这种情况下,都没有。 Array#someMDN | 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。)

我应该注意,您的示例实现都不起作用,forEachreduce都不起作用。 forEach一个将始终返回false,因为回调中的return true只是从回调中返回而根本没有任何效果。 reduce将导致A)无法测试数组中的第一个条目; B)只告诉你数组中的 last 条目是否是偶数,而不是之前的任何条目是否为;和C)如果在只有一个条目的数组上调用,则返回第一个条目的,而不是truefalse

正确的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;

===的结果是已经一个布尔值。