2016-09-19 84 views
2

我想抽象出传递到我的数组'reduce()函数中的函数,使函数成为通用'Array reducer中最大的函数'。为了达到这个目的,我想在reduce()参数中传递不同的特定功能,以便能够指定比较标准。在我的例子,这些是线更高阶的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()制作两个不同的功能来实现结果,但这并不满足我。我想知道是否有办法以不同的方式做。因此,它返回一个比较两名球员,而不是比较球员本身的功能

变化topPlayerReducer实施:

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

然后你

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); 
} 

回答

5

我会做它像这样可以拨打reduce这样的:

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

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

这样,您就可以与您对reduce每个不同的调用自定义函数传递,你只是在topPlayerReducer第一“包起来”。我认为这是你想用bind实现的目标。


FYI:我认为你正在寻找从bind被称为部分应用程序,在那里你把一个函数与多个参数的东西,提供一些但不是所有的参数,并返回一个函数期待剩下的论点。 你可以用bind做到这一点,但你要记住:

  1. 结合采用这势必会在函数内部this一个额外的参数,
  2. 你是论据“预加载”将填补从离开

所以,如果你犯了这些变化您尝试使用绑定会工作:

// 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版本只是添加了混乱在这种情况下。 bind可以用于具有使用this的功能,但您需要一种方法来更改其值。

+0

工作!有点难以相信它是如何工作的,但我想我明白了。 – db2791

+0

很酷。基本上,随着新的实现,每次调用'topPlayerReducer'时,它都会返回一个全新的函数,它会接收两个玩家并返回满足条件的玩家。你用这种方式创建的函数与你直接定义的函数相同,所以你可以将它传递给'reduce'和所有好东西。 如果你想让你的头稍微多一点,可以尝试用'topPlayerReducer'调用一下:在命令行/控制台调用'var foo = topPlayerReducer(someFunc)'。然后你可以看到'foo'是什么,尝试用一些参数来调用它。 – Peter