【问题标题】:Higher-order reduce() function高阶 reduce() 函数
【发布时间】:2016-09-19 01:55:44
【问题描述】:

我想抽象传递给我的数组的reduce() 函数的函数,以使该函数成为一个通用的“最伟大的 Array reducer”。为此,我想在reduce() 参数中传入不同的特定函数,以便能够指定比较标准。在我的示例中,这些是行

return players.reduce(topPlayerReducer, players[0], getThreePointerPercentage);

return players.reduce(topPlayerReducer, players[0], getReboundNumber);

其中topPlayerReducer 是传递给reduce() 的通用函数,它根据某些标准查找数组中的最大项。我的标准是第三个论点。如何合并我的特定比较函数(getThreePointerPercentagegetReboundNumber)以便保持这种抽象级别?现在,我收到fn 不是topPlayerReducer 中的函数的错误。我对此并不感到惊讶,因为我的其他功能不在范围内。我也试过做

var reboundReducer = topPlayerReducer.bind(getReboundNumber);

return gameInfo.players.reduce(reboundReducer, players[0]);}

但我遇到了同样的错误。

我意识到我可以通过为reduce() 制作两个不同的函数来获得一个结果,但这并不能让我满意。我想知道是否有不同的方法。

function getGuardWithMostThreePointers(gameInfo){
    return players.reduce(topPlayerReducer, players[0], getThreePointerPercentage);
}

function getPlayerWithMostRebounds(gameInfo){
    return players.reduce(topPlayerReducer, players[0], getReboundNumber);
}

function topPlayerReducer(topPlayer, currentPlayer, fn){
    if (fn(currentPlayer) > fn(topPlayer)){
        return currentPlayer;
    } else {
        return topRebounder;
    }
}

function getReboundNumber(player){
    return parseInt(player.rebounds_offensive) + parseInt(player.rebounds_defensive);
}

function getThreePointerPercentage(player){
    return parseInt(player.three_pointers_made) / parseInt(player.three_pointers_attempted);
}

【问题讨论】:

    标签: javascript reduce higher-order-functions


    【解决方案1】:

    我会这样做:

    更改topPlayerReducer 的实现,使其返回一个比较两个玩家的函数,而不是比较玩家本身:

    function topPlayerReducer(fn){
        return function(topPlayer, currentPlayer) {
            if (fn(currentPlayer) > fn(topPlayer)){
                return currentPlayer;
            } else {
                return topPlayer;
            }
        }
    }
    

    然后你可以像这样拨打reduce

    return pointGuards.reduce(topPlayerReducer(getThreePointerPercentage), pointGuards[0]);
    

    return gameInfo.players.reduce(topPlayerReducer(getReboundNumber), gameInfo.players[0]);
    

    通过这种方式,您可以在对reduce 进行的每个不同调用中传入一个自定义函数,您只需首先将其“包装”在topPlayerReducer 中。我认为这就是您试图通过bind 实现的目标。


    仅供参考:我认为您从bind 中寻找的东西称为部分应用程序,您可以在其中获取具有多个参数的函数,提供一些但不是全部参数,然后返回一个期望剩余参数的函数。 您可以使用bind 执行此操作,但您必须记住:

    1. bind 需要一个额外的参数,该参数绑定到函数内的this
    2. 您正在“预加载”的参数将从左侧填写。

    因此,如果您进行了这些更改,那么您使用 bind 的尝试将会奏效:

    // Make fn the leftmost parameter
    function topPlayerReducer(fn, topPlayer, currentPlayer){
        if (fn(currentPlayer) > fn(topPlayer)){
            return currentPlayer;
        } else {
            return topRebounder;
        }
    }
    
    // Add an extra 'null' argument to be bound to the `this` variable
    return players.reduce(topPlayerReducer.bind(null, getReboundNumber), players[0])
    

    为了我的钱,bind 版本只是在这种情况下增加了混乱。但是,当您拥有使用 this 的函数并且您需要一种方法来更改其值时,bind 会很有用。

    【讨论】:

    • 成功了!有点难以相信它是如何工作的,但我想我明白了。
    • 酷。基本上,在新的实现中,每次调用topPlayerReducer 时,它都会返回一个全新的函数,该函数需要两个玩家并返回满足条件的玩家。您以这种方式创建的函数与您直接定义的函数相同,因此您可以将其传递给reduce 以及所有这些好东西。如果您想进一步了解它,请尝试稍微摆弄topPlayerReducer:在命令行/控制台调用var foo = topPlayerReducer(someFunc)。然后你可以看到foo是什么,尝试用一些参数等调用它。
    猜你喜欢
    • 1970-01-01
    • 2016-05-07
    • 1970-01-01
    • 2017-04-21
    • 1970-01-01
    相关资源
    最近更新 更多