我在使用此功能时遇到了多个问题。这是数据结构和算法课程的奖金问题的一部分,我在这一个问题上花了很多时间,我真的很想让它工作并理解发生了什么。
有一个主要问题,导致了几个小问题......这个问题的名字是JavaScript。我们以前从未在JavaScript中编程,但出于某种原因我们必须使用它。
该函数必须通过测试(这个和斐波那契),结构如下:
var fn = (n) => 2 * n
var m_fn = memoize(fn)
expect(m_fn(18)).to.equal(fn(18))
所以我必须传递我想要memoize的函数作为memoize函数的参数,memoize函数必须返回一个函数。我不允许以任何其他方式这样做。
我完成了所有阅读并研究了memoize函数,但所有实现都采用了不同的方法。
基本上,我明白我必须做什么,但我不太明白。我知道memoize函数应该做什么,但我不明白如何使用memoize函数调整原始函数。这就是我到目前为止/我没有的东西:
我知道这是错的。但我想我错过了一些重要的东西。我应该返回一个函数,但我正在返回值......
在测试中,它是写入var m_fn = memoize(fn),所以memoize函数传递fn,然后返回一个新函数,但在我的memoize中,我返回fn(n)的值,所以我在做某事错...
/**
* Creates a memoized version of the function fn. It is assumed that fn is a referentially transparent
* function.
* @param {function} fn Some referentially transparent function that takes a basic datatype (i.e. number / string)
* @returns {function} A new function that is the memoized version of fn. It never calculates the result of
* a function twice.
*/
memoize: (fn) => { //here we enter the function that we want to memoize
var memory = []; //we need to create an array to hold the previously calculated values, length n (parameter of fn)
if(this.n > memory.length){ //Check to see if this particular value is in the array already.
return memory[this.n]; //How do I access the integer parameter that was passed through fn though? Is this correct?
} else{ // if not, we want to save it and return it
var result = fn(this.n);
memory.push(result);
return result;
}
}
答案 0 :(得分:2)
确实,您需要返回一个函数。
其次,数组不是[[FunctionLocation]]
的理想结构,因为它需要线性时间来查找其中的参数值。我建议使用Map
来实现这一目的。它有memory
,has()
和get()
方法,可以在接近恒定的时间内运行:
set()

答案 1 :(得分:1)
答案 2 :(得分:0)
查看您的代码和代码内注释,并假设我正确地解释,您真的非常接近解决方案。正如您在问题中所说,您需要返回一个函数,它返回值而不是返回值。
请参阅注释以获取解释:
function memoize(f) {
// An array in which to remember objects with the input arg and result
var memory = [];
// This is the function that will use that array; this is the
// return value of memoize
return function(arg) {
// This code runs when the function returned by memoize is called
// It's *here* that we want to process the argument, check the `memory`
// array, call `f` if necessary, etc.
var entry;
// See if we have a previously-saved result for `arg`
var entry = memory.find(entry => entry.arg === arg);
if (!entry) {
// No -- call `fn`, remember the `arg` and result in an object
// we store in memory``
entry = {arg, result: f(arg)};
memory.push(entry);
}
// We have it (now), return the result
return entry.result;
};
}
function fn(arg) {
console.log("fn called with " + arg);
return 2 * arg;
}
var m_fn = memoize(fn);
console.log(m_fn(18));
console.log(m_fn(18));
console.log(m_fn(20));
console.log(m_fn(20));

注意:您的代码中有一个箭头功能,所以我认为可以使用上面的ES2015功能。但实际上并不是很多,只是传递给memory.find
的箭头函数,假设Array#find
可用,以及用于创建条目对象的语法(在ES5中)我们需要entry = {arg: arg, result: f(arg)}
代替。)
请注意,如果我们可以假设arg
将是一个字符串或数字或其他值可以可靠地转换为字符串,我们可以使用一个对象来存储数据而不是数组。
实际上,鉴于这是ES2015,我们可以使用Map
:
function memoize(f) {
// An Map in which to remember objects with the input arg and result
const memory = new Map();
// This is the function that will use that array; this is the
// return value of memoize
return function(arg) {
// This code runs when the function returned by memoize is called
// It's *here* that we want to process the argument, check the `memory`
// array, call `f` if necessary, etc.
let result;
// See if we have a previously-saved result for `arg`
if (!memory.has(arg)) {
// No -- call `fn`, remember the `arg` and result in an object
// we store in memory``
result = f(arg);
memory.set(arg, result);
} else {
// Yes, get it
result = memory.get(arg);
}
// We have it (now), return the result
return result;
};
}
function fn(arg) {
console.log("fn called with " + arg);
return 2 * arg;
}
var m_fn = memoize(fn);
console.log(m_fn(18));
console.log(m_fn(18));
console.log(m_fn(20));
console.log(m_fn(20));

请注意,在这两种情况下,我都会详细地编写代码,以便进行评论和轻松理解。特别是Map
的ES2015版本可以相当更短。