”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 切勿两次调用同一个函数(使用记忆功能)

切勿两次调用同一个函数(使用记忆功能)

发布于2024-08-15
浏览:960

Never call the same function twice (with memoization)

所以我刚刚发现了这个有趣的记忆化小概念。

我已经开始阅读有关它的文章,当我抓住这个想法的尾巴时就停止了。

然后我决定以我自己的方式并以我理解的方式找出简单的解决方案。

如果您从未听说过,记忆是存储函数执行结果的过程,因此您可以在下次使用相同参数运行该函数时从一个小(或不那么大)缓存中提取它。

实际上,这对于高资源消耗的功能很有用。它伴随着使用额外空间作为缓存的成本。但它可以提高代码的速度以及使用它的用户的体验。

我玩了一下 JS 代码并提出了这个解决方案:

const memoize = fn => {
  const cache = {}
  return (...args) => {
    const fnKey = `${fn.name}(${args})`;
    if(!cache[fnKey]) {
      cache[fnKey] = fn(...args);
    }

    return cache[fnKey]
  };
}

然后你可以像这样运行它:

function _add(x, y) {
  console.log("function runs", x, y);
  return x   y;
}

const add = memoize(_add)

add(42, 69)
add(10, 15)
add(10, 15)

这会导致函数执行两次(#1 和 #2 'add' 调用)。第三个“添加”调用将使用缓存,因为它与#2 调用相同。

'function runs' 42 69
'function runs' 10 15

可以看到'function running' 10 15只被调用了一次。这是因为我们第二次调用它时,缓存正在被使用。

现在让我们快速分解一下这里发生的事情。

在这个例子中我们利用闭包机制来存储缓存。

const memoize = fn => {
  const cache = {}
  return () => {

  };
}

这允许我们抛出“fn”参数,这是最重要的,因为这正是我们想要操作的函数,向下作用域并“监听”它的每个执行。

我确实是用最简单、最天真的方式写的。因此,我们将使用带有参数的函数名称作为缓存的键,并将其执行结果作为值。

这意味着,执行:

add(2, 2)

结果为

// Our cache
{
  'add(2, 2)': 4
}

缓存值。

我知道这可能不完全是“正确的方式”。但这个练习和这篇文章的想法并不是关于经过充分测试的安全和无边缘情况的解决方案。

这是关于学习和简单的实施。关于概念。所以我现在不关注实施细节。

现在,我们首先弄清楚函数调用的关键:

const memoize = fn => {
  const cache = {}
  return (...args) => {
    const fnKey = `${fn.name}(${args})`;
  };
}

我们将使用它来将函数执行的结果存储在缓存中。

然后我们检查这个键(fnKey)是否已经存在。如果没有,我们将键及其值设置为传递的函数执行的结果。

最后我们总是从缓存中返回结果。因此,传递给 memoize 方法的函数的执行实际上总是以闭包结束(在“缓存”对象中)。

我们现在只操作这个对象:

const memoize = fn => {
  const cache = {}
  return (...args) => {
    const fnKey = `${fn.name}(${args})`;
    if(!cache[fnKey]) {
      cache[fnKey] = fn(...args);
    }

    return cache[fnKey]
  };
}

就是这样。

现在我要去看看应该如何“正确”地完成它。但如果您觉得这很有趣,请告诉我。如果这种方法有任何不清楚或错误的地方(根据您的口味),请删除评论,让我们讨论一下。

谢谢,再见!

版本声明 本文转载于:https://dev.to/baypanic/never-call-the-same-function-twice-with-memoization-167f?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 为什么使用固定定位时,为什么具有100%网格板柱的网格超越身体?
    为什么使用固定定位时,为什么具有100%网格板柱的网格超越身体?
    网格超过身体,用100%grid-template-columns 为什么在grid-template-colms中具有100%的显示器,当位置设置为设置的位置时,grid-template-colly修复了?问题: 考虑以下CSS和html: class =“ snippet-code”> g...
    编程 发布于2025-07-21
  • 如何在Java的全屏独家模式下处理用户输入?
    如何在Java的全屏独家模式下处理用户输入?
    Handling User Input in Full Screen Exclusive Mode in JavaIntroductionWhen running a Java application in full screen exclusive mode, the usual event ha...
    编程 发布于2025-07-21
  • 如何从Python中的字符串中删除表情符号:固定常见错误的初学者指南?
    如何从Python中的字符串中删除表情符号:固定常见错误的初学者指南?
    从python import codecs import codecs import codecs 导入 text = codecs.decode('这狗\ u0001f602'.encode('utf-8'),'utf-8') 印刷(文字)#带有...
    编程 发布于2025-07-21
  • Java为何无法创建泛型数组?
    Java为何无法创建泛型数组?
    通用阵列创建错误 arrayList [2]; JAVA报告了“通用数组创建”错误。为什么不允许这样做?答案:Create an Auxiliary Class:public static ArrayList<myObject>[] a = new ArrayList<myO...
    编程 发布于2025-07-21
  • C++中如何将独占指针作为函数或构造函数参数传递?
    C++中如何将独占指针作为函数或构造函数参数传递?
    在构造函数和函数中将唯一的指数管理为参数 unique pointers( unique_ptr [2启示。通过值: base(std :: simelor_ptr n) :next(std :: move(n)){} 此方法将唯一指针的所有权转移到函数/对象。指针的内容被移至功能中,在操作...
    编程 发布于2025-07-21
  • Python中何时用"try"而非"if"检测变量值?
    Python中何时用"try"而非"if"检测变量值?
    使用“ try“ vs.” if”来测试python 在python中的变量值,在某些情况下,您可能需要在处理之前检查变量是否具有值。在使用“如果”或“ try”构建体之间决定。“ if” constructs result = function() 如果结果: 对于结果: ...
    编程 发布于2025-07-21
  • 如何在JavaScript对象中动态设置键?
    如何在JavaScript对象中动态设置键?
    在尝试为JavaScript对象创建动态键时,如何使用此Syntax jsObj['key' i] = 'example' 1;不工作。正确的方法采用方括号: jsobj ['key''i] ='example'1; 在JavaScript中,数组是一...
    编程 发布于2025-07-21
  • 在JavaScript中如何并发运行异步操作并正确处理错误?
    在JavaScript中如何并发运行异步操作并正确处理错误?
    同意操作execution 在执行asynchronous操作时,相关的代码段落会遇到一个问题,当执行asynchronous操作:此实现在启动下一个操作之前依次等待每个操作的完成。要启用并发执行,需要进行修改的方法。 第一个解决方案试图通过获得每个操作的承诺来解决此问题,然后单独等待它们: co...
    编程 发布于2025-07-21
  • JavaScript计算两个日期之间天数的方法
    JavaScript计算两个日期之间天数的方法
    How to Calculate the Difference Between Dates in JavascriptAs you attempt to determine the difference between two dates in Javascript, consider this s...
    编程 发布于2025-07-21
  • 在GO中构造SQL查询时,如何安全地加入文本和值?
    在GO中构造SQL查询时,如何安全地加入文本和值?
    在go中构造文本sql查询时,在go sql queries 中,在使用conting and contement和contement consem per时,尤其是在使用integer per当per当per时,per per per当per. 在GO中实现这一目标的惯用方法是使用fmt.spr...
    编程 发布于2025-07-21
  • PHP阵列键值异常:了解07和08的好奇情况
    PHP阵列键值异常:了解07和08的好奇情况
    PHP数组键值问题,使用07&08 在给定数月的数组中,键值07和08呈现令人困惑的行为时,就会出现一个不寻常的问题。运行print_r($月份)返回意外结果:键“ 07”丢失,而键“ 08”分配给了9月的值。此问题源于PHP对领先零的解释。当一个数字带有0(例如07或08)的前缀时,PHP将...
    编程 发布于2025-07-21
  • Async Void vs. Async Task在ASP.NET中:为什么Async Void方法有时会抛出异常?
    Async Void vs. Async Task在ASP.NET中:为什么Async Void方法有时会抛出异常?
    在ASP.NET async void void async void void void void void的设计无需返回asynchroncon而无需返回任务对象。他们在执行过程中增加未偿还操作的计数,并在完成后减少。在某些情况下,这种行为可能是有益的,例如未期望或明确预期操作结果的火灾和...
    编程 发布于2025-07-21
  • 如何高效地在一个事务中插入数据到多个MySQL表?
    如何高效地在一个事务中插入数据到多个MySQL表?
    mySQL插入到多个表中,该数据可能会产生意外的结果。虽然似乎有多个查询可以解决问题,但将从用户表的自动信息ID与配置文件表的手动用户ID相关联提出了挑战。使用Transactions和last_insert_id() 插入用户(用户名,密码)值('test','test...
    编程 发布于2025-07-21
  • 为什么使用Firefox后退按钮时JavaScript执行停止?
    为什么使用Firefox后退按钮时JavaScript执行停止?
    导航历史记录问题:JavaScript使用Firefox Back Back 此行为是由浏览器缓存JavaScript资源引起的。要解决此问题并确保在后续页面访问中执行脚本,Firefox用户应设置一个空功能。 警报'); }; alert('inline Alert')...
    编程 发布于2025-07-21
  • Go语言如何动态发现导出包类型?
    Go语言如何动态发现导出包类型?
    与反射软件包中的有限类型的发现能力相反,本文探讨了在运行时发现所有包装类型(尤其是struntime go import( “ FMT” “去/进口商” ) func main(){ pkg,err:= incorter.default()。导入(“ time”) ...
    编程 发布于2025-07-21

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3