【问题标题】:Implementing memoize pattern in JavaScript for multiple values在 JavaScript 中为多个值实现 memoize 模式
【发布时间】:2019-04-16 15:40:27
【问题描述】:

我正在尝试使用 JavaScript 实现多个值的记忆模式。 我设法编写了单个值的代码:

var lazy = {};
lazy.memoization = evaluator => {
  const cache = new Map;

  return key => {
    cache.has(key) || cache.set(key, evaluator(key));

    return cache.get(key);
  };
};

var memoize = lazy.memoization(key => console.log('computing ', key));
memoize(1); // -> computing 1
memoize(2); // -> computing 2

这里是多个键的版本,它没有按预期工作,它只是输出'computing Array []','computing undefined':

var lazy = {};
lazy.memoization = evaluator => {
  const cash = new Map;

  return (...keys) => {
    var values = [];
    keys.reduce((v, f) => {
      if (!cash.has(v)) {
        cash.set(v, evaluator(v));
      }

      values.push(cash.get(v));
    }, values);

    return values;
  };
};

var memoizeMultiple = lazy.memoization((...keys) => {
  keys.forEach(key => console.log('computing ', key))
});
memoizeMultiple(1, 2);

这里有什么问题?

【问题讨论】:

  • 您正在为传入的每个参数运行evaluator。这是有意还是应该缓存使用所有参数调用evaluator 的结果?
  • 更重要的是,您提到“它没有按预期工作”,但不要告诉我们您的期望:)。
  • reduce 调用存在几个问题:您使用v 好像它是密钥,但密钥是f;你没有从回调中返回任何东西,所以在随后的旅行中vundefined;你没有使用返回值(这几乎总是意味着你不应该使用reduce)。
  • 在单独的注释中,cache 是存储在内存中的正确术语(在这种情况下)。 “现金”是指金钱。
  • @VLAZ 是的,你说得对,感谢您对“现金”的评论。

标签: javascript memoization


【解决方案1】:

您的代码存在很多问题。首先,reducefold 的一种,这意味着它通常用于将数据结构“折叠”成单个值。为此,传递给reduce 的函数首先获取累加 值,然后是数据结构中的每个值。

const sumOf = ns => ns.reduce((sum, num) => sum + num, 0);

sumOf([1, 2, 3, 4, 5]); // -> 15

在本例中,数据结构是Array,其中包含Number 值。 reduce 用于将数组中的所有数字折叠成最终值(通过将它们相加)。折叠函数称为 reducer 函数(在本例中它是加法)。最后,传递给 reduce 的 0seed 值。

让我们一步一步追踪发生了什么:

在第一次迭代中,reducer 函数被传递种子值和数组中的第一个数字。因此它看起来像:

(0, 1) => 0 + 1

第二次迭代以第一次迭代的结果作为累加器值和数组中的第二个数字开始:

(1, 2) => 1 + 2

所以总的来说,它的工作原理是这样的:

(0, 1) => 0 + 1
(1, 2) => 1 + 2
(3, 3) => 3 + 3
(6, 4) => 6 + 4
(10, 5) => 10 + 5

在最后一次迭代之后,reduce 返回最终的累加器,在本例中为 15

好的,回到您提供的代码。您的“多参数记忆”版本使用reduce,但reducer 函数不会将中间结果作为新的累加器值返回,您也不会返回reduce 产生的最终结果。

另一个问题是你的evaluator 函数。它返回的值存储在缓存Map 实例中。在您的代码中,它除了undefined 不返回任何内容。因此,undefined 被存储并在后续调用 memoized 函数时返回。

如果我们解决了这些问题,它就会起作用:

var lazy = {};
lazy.memoization = evaluator => {
  const cache = new Map();
  return (...args) => {
    return args.reduce((acc, arg) => {
      if (!cache.has(arg)) {
        cache.set(arg, evaluator(arg)); // stores the returned value inside the cache variable
      }

      return acc.concat(cache.get(arg));
    }, []); // the result should be an array, so use that as the seed
  };
};

var memoizeMultiple = lazy.memoization(value => {
  console.log('computing ', value)
  return value; // you have to return something in here, because the return value is stored
});

memoizeMultiple(1, 2);

我希望这能澄清一点。编码愉快!

【讨论】:

  • 很好的解释。谢谢。
猜你喜欢
  • 2014-08-20
  • 2021-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多