#typescript
Вопрос:
Допустим, у нас есть метод, который мы хотели бы, чтобы он возвращал тот же последний результат, если ни один из его параметров не изменился с момента последнего вызова. Как мы должны проверить, не изменились ли его параметры? Кэшировать параметры в объекте? массив? для более поздней проверки.
Compute( p1:boolean, p2:number, p3:number) {
// if any of p1 or p2 or p3 have changed from last invocation
// then redo computation
// else return last result.
}
В прошлом, когда я имел дело с одним параметром, я использовал поле типа p1_last и сравнивал его с ним при вводе.
что-то вроде этого
if (p1 == this.p1_last) {
return this.result
}
else {
this.p1_last = p1 // save p1 for next invocation.
result = ....some algo....
return this.result
}
Ваши мысли и предложения оценены по достоинству. Спасибо.
Ответ №1:
Если количество параметров фиксировано, проверка массива должна быть тривиальной:
let lastParams: [boolean, number, number];
let lastResu< // type this properly...
function Compute( p1:boolean, p2:number, p3:number) {
if (
lastParams amp;amp;
lastParams[0] === p1 amp;amp;
lastParams[1] === p2 amp;amp;
lastParams[2] === p3
) {
return lastResu<
}
lastResult = /* some computation */
lastParams = [p1, p2, p3];
return lastResu<
}
Ответ №2:
Вы можете создать общую функцию, которая запоминает входные данные для переданной функции.
function memorize<F extends (...args: any) => any>(func: F): F {
const cache = new Map()
return function (this: unknown, ...args: unknown[]): unknown {
// update the key calculation according to type of args
const argsKey = args.toString()
const cacheValue = cache.get(argsKey)
if (cacheValue) console.log('cache working')
if (cacheValue) return cacheValue
const result = func.apply(this, args)
cache.set(argsKey, result)
return result
} as F
}
let compute = function (p1: boolean, p2: number, p3: number) {
// sample computation
if (p1) return p2 * p3
return p2 p3
}
compute = memorize(compute)
let x = compute(true, 1, 2)
console.log(x)
x = compute(true, 1, 2) // cached
console.log(x)
x = compute(false, 1, 2)
console.log(x)
x = compute(false, 1, 2) // cached
console.log(x)
x = compute(false, 3, 2)
console.log(x)
x = compute(false, 3, 2) // cached
console.log(x)
x = compute(true, 1, 2) // cached
console.log(x)
Комментарии:
1. Ух ты! интересное решение, у вас, наверное, антенны на макушке 🙂 Мне нужно потратить час, чтобы понять весь тот синтаксис запоминания, который вы использовали 🙂 но я своего рода программист, который использует вещи в черных ящиках. Это, вероятно, неприменимо к большим данным, возможно, излишне в моей ситуации. Мне нравится, как после вычисления = запоминания(вычисления) вы как бы переопределяете вычисления, и использование естественно. Я приму это как решение/ответ, поскольку я могу использовать его в будущем. Спасибо вам за то, что поделились своими знаниями.
2. @Meryan Добро пожаловать! Возможно, вам потребуется внести изменения
const str = args.toString()
в соответствии с вашим вариантом использования и в зависимости от типа параметровfunc
, которые вы можете использовать. Немного обновлен ответ!
Ответ №3:
Как насчёт
private ComputeLastParams = {}
private ResultLast
Compute( p1:boolean, p2:number, p3:number) {
if ( ObjectEqual ( {p1, p2, p3}, this.ComputeLastParams )
) {
return this.ResultLast
}
//
this.ResultLast = /* some computation */
this.ComputeLastParams = {p1, p2, p3}
return this.ResultLast
}
static ObjectEqual(object1, object2) {
const keys1 = Object.keys(object1);
const keys2 = Object.keys(object2);
if (keys1.length !== keys2.length) {
return false;
}
for (let key of keys1) {
if (object1[key] !== object2[key]) {
return false;
}
}
return true;
}