javascript - underscore.js _.memoize() 在行动中的例子?

标签 javascript coffeescript underscore.js sicp memoization

任何人都可以给我一个 underscore.js _.memoize() 的例子吗?

最好使用 hashFunction,在 coffeescript 中更好?

这是 coffeescript 中来自 SICP 的那个可爱的更改计数函数的一个稍微修改的版本:

countChange = (amount)->

  cc = (amount, kindsOfCoins)->

    firstDenomination = (kindsOfCoins)->
      switch kindsOfCoins
        when 1 then 1
        when 2 then 5
        when 3 then 10
        when 4 then 25

    if amount is 0 then 1
    else if amount < 0 or kindsOfCoins is 0 then 0
    else 
      (cc amount, (kindsOfCoins - 1)) + 
      (cc (amount - firstDenomination(kindsOfCoins)), kindsOfCoins)

  cc amount*100, 4


console.log "Ways to make change for $0.85: " + countChange(.85)

例如,我如何在上面使用下划线的 _.memoize()?

非常感谢!

ps..另外,请不要犹豫,在函数的编码方式中找出漏洞..我对 coffeescript 很陌生,也欢迎任何帮助使该代码更地道的帮助。

最佳答案

此处 memoize 的一个用途是减少对内部 cc 函数的调用次数:

n = 0
countChange = (amount)->
  firstDenomination = (kindsOfCoins) ->
    [1, 5, 10, 25][kindsOfCoins - 1]

  cc = (amount, kindsOfCoins)->
    ++n # This is just a simple counter for demonstration purposes
    return 1 if amount is 0
    return 0 if amount < 0 or kindsOfCoins is 0
    (cc amount, (kindsOfCoins - 1)) +
      (cc (amount - firstDenomination(kindsOfCoins)), kindsOfCoins)

  cc = _.memoize cc, (a,k) -> "#{a},#{k}"

  cc amount*100, 4

console.log "Ways to make change for $0.85: #{countChange(.85)}"
​console.log "#{n} iterations of cc"

为了紧凑,我还重新安排了一些东西,我将 firstDenomination 移到了 cc 之外,以简化 cc ;我的 firstDenomination是否比你的好是个人品味问题,我有偏见反对使用 switch 来实现简单的查找表,但 YMMV。

内存版本说“cc 的 211 次迭代”,演示:http://jsfiddle.net/ambiguous/FZsJU/

非内存版本显示“cc 的 8141 次迭代”,演示:http://jsfiddle.net/ambiguous/Xn944/

因此,非记忆化版本调用 cc 的频率提高了约 40 倍。根据散列函数的计算开销(我的足以用于演示目的但未完全优化)和缓存查找的开销,内存可能值得也可能不值得。这是内存时要问的标准问题:缓存是否比缓存的计算更快?

如果我们看一下 _.memoize 的实现:

// Memoize an expensive function by storing its results.
_.memoize = function(func, hasher) {
  var memo = {};
  hasher || (hasher = _.identity);
  return function() {
    var key = hasher.apply(this, arguments);
    return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
  };
};

然后您可以看到它是如何工作的以及如何使用hashermemo对象用作缓存,hasher用于将memoized函数的参数转换为memo中的键;如果我们找到键,那么我们可以立即返回缓存的值,否则我们会以(大概)慢速的方式计算它,缓存它,然后返回它。

关于javascript - underscore.js _.memoize() 在行动中的例子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10168219/

相关文章:

Meteor 自定义包中的 CoffeeScript 命名空间导出

jquery - 将 jQuery 移植到 CoffeeScript?

javascript - Canvas 的 drawImage() 不进行子像素渲染/抗锯齿是否存在技术原因?

javascript - 在 adobe pro 中复制粘贴动态图章

javascript - 如何在 native react 中设置背景图像?

javascript - 使用 Underscore.js 的 lastIndexOf 调用

javascript - 'use strict' 和 underscore.js 问题

javascript - Bootstrap Collapse show.bs.collapse 第二次不工作

coffeescript - 使用 Coffeescript.compile 时访问裸选项

javascript - 克隆一个对象的元素并推送到它的自身