【问题标题】:Javascript MemoizationJavascript 记忆
【发布时间】:2013-12-04 21:44:37
【问题描述】:

有人可以提供一个仅使用 Javascript 即可记忆的简单功能。 google的时候在网上找了几篇文章,但是没看到很多。我发现的最好的文章是这篇文章:

http://alivedise.github.io/blog/2012/12/22/javascript-memorization/

我明白什么是缓存,但是这个例子对我来说太复杂了。我希望这里的任何人都可以提供一个简单的函数和调用,以便我可以接受并开始更深入地理解这一点。

谢谢

【问题讨论】:

  • 该技术的名称实际上是“memoization”。谷歌搜索可能会带来更多结果。
  • 好的,现在就这样做。感谢马丁的投入

标签: javascript memoization


【解决方案1】:

我认为您正在寻找的是 memoization

来自Wikipedia

记忆是一种优化技术,主要用于通过函数调用避免重复计算先前处理的输入的结果来加速计算机程序

有一篇很好的文章 here 和另一个 SO 问题 here

您通常会使用记忆化来减少重复计算始终相同的结果的成本。任何性能改进都以为缓存结果分配内存为代价。

代码中的一个简单示例:

var cachedResult;
function doHeavyCalculation()
{
    if (typeof(cachedResult) !== 'undefined')
        return cachedResult;

    // no cached result available. calculate it, and store it.
    cachedResult = /* do your computation */;
    return cachedResult;
}

有一些 JavaScript 框架支持记忆任何函数,它们基本上通过装饰函数以可重用的方式为您提供这些样板代码。

【讨论】:

  • 嘿,德鲁,我看到了那篇文章。感谢您提供的 SO 示例,这对您有很大帮助!
  • 我认为这个答案可以改进。对我来说,现在看起来你假设函数每次都返回相同的值(如果 cachedResult 未定义,则将值分配给 var,如果没有,则从 var 中获取),/*do your computation*/ 留下了很多想象力。
  • @ArturTagisow memoization 就是这样:为给定的参数列表返回相同的结果。在这个例子中,没有参数,所以缓存只是一个值。如果您有一个参数列表,那么内存/缓存将需要考虑到这一点。
【解决方案2】:

我认为你的意思是 memoization,这基本上意味着记住你已经计算过的东西。以下是使用记忆的斐波那契算法。

var cache = {1:1, 2:1};
function fib(n) {
    if(!cache[n]) // Have we already calculated this value?
       cache[n] = fib(n - 1) + fib(n - 2)  // Calculate and store it

    return cache[n]
}

【讨论】:

    【解决方案3】:

    恐怕所有其他答案都使用全局变量,这是错误的。 JavaScript 提供了更好的解决方案。请注意函数表达式后面的括号 ()。这意味着该函数立即被触发,并且该函数返回的结果(并分配给 memo 常量)是另一个函数,它自己进行计算,但可以使用缓存作为已经触发的上下文中的变量功能。缓存只能由备忘录功能访问。

    const memo = function () {
      let cache = [];
      return function (n) {
        if (cache.includes(n)) { console.log("already in memory") }
        else { console.log("first"); cache.push(n); }
      }
    }();
    
    memo(7) //first
    memo(7) //already in memory
    memo(7) //already in memory
    memo(1) //first
    memo(1) //already in memory
    

    【讨论】:

      【解决方案4】:

      keslert 的斐波那契例子是一个很好的例子,这里还有一个以编辑距离为例供您理解。

      // Map<string, Map<string, number>>
      const cache = new Map();
      
      // a: string, b: string
      function editDistance(a, b) {
          if (a.length === 0) {
              return b.length;
          }
          if (b.length === 0) {
              return a.length;
          }
          let res = cache.getMap(a).get(b);
          if (res !== undefined) {
              return res;
          }
          res = Math.min(
              editDistance(pop(a), pop(b)) + (last(a) === last(b) ? 1 : 0)
              , editDistance(pop(a), b) + 1
              , editDistance(a, pop(b)) + 1
          );
          cache.getMap(a).set(b, res);
          return res;
      }
      

      值得一提的是,在某些情况下,直接进行计算比查找内存(缓存)成本更低。例如基本的逻辑运算或几步数学运算。

      要详细确定具体情况,您需要了解缓存使用的机制(数据结构、操作复杂性,甚至存储介质(即您是使用快速 RAM 还是交换到慢速硬盘?))这是依赖于浏览器/JavaScript引擎的实现。

      来源:https://github.com/beenotung/programming-class/blob/3f678ac48511d829149fb06c139e53cc2680ae82/edit-distance/edit-distance.ts

      -- 编辑 2018 Mar 06, 13:56

      在示例中,对 pop/1 函数的调用也可以被缓存。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多