javascript - 递归替换函数需要说明
问题描述
嗨,我对 javascript 编程很陌生。我正在学习 FCC 和 Grasshopper。在 Grasshopper 上,我被困在关于递归替换功能的课程上。我不明白。如果有人解释,这将是一个很大的帮助。所以根据教训,它是这样的:
var wrongDocument = "This document ahs a typo in it. The other one ahs typo too.";
function changeSpelling(string, oldPart, newPart) {
if (string.includes(oldPart) === false) {
return string;
}
string = string.replace(oldPart, newPart);
return changeSpelling(string, oldPart, newPart);
};
console.log(wrongDocument);
console.log(changeSpelling(wrongDocument, 'ahs', 'has'));
我面临的问题是我不明白 return 语句为什么以及如何调用它所在的函数?
其次,为什么这不能用 if...else 语句来解释?第三,我在理解参数和参数时遇到问题。所以我写了以下代码。这绝对不会取代所有的拼写,但我无法进一步理解。
var chat = "This document ahs a typo in it. The other one ahs too.";
var fix = (a, b) => {
if (chat.includes(a) === false) {
return chat;
}
else {
return chat.replace(a, b)
}
}
console.log(chat);
console.log(fix('ahs', 'has'));
请解释递归函数的工作原理以及我的代码有什么问题。
解决方案
我面临的问题是我不明白 return 语句为什么以及如何调用它所在的函数?
你是对的。这将是一个大问题,递归将永远追逐它的尾巴,除了这一点:
if (string.includes(oldPart) === false) {
return string;
}
所以递归调用 ( return changeSpelling(string, oldPart, newPart)
) 不是从函数返回的唯一方法。还有至少一个(在这种情况下只有一个)基本情况在没有递归调用的情况下返回。此外,每次递归调用都会朝着基本情况前进,因为每次出现特定错字的实例都会减少一次。如果这两个是真的,那么递归调用是定义良好的。
您的替代解决方案仅替换错字的第一个实例。这就是它的设计目的。有几种方法可以解决这个问题。也许最明显的一个是将您的代码包装在一个while
循环中,如下所示:
const fix = (chat, a, b) => {
if (chat .includes (a) === false) {
return chat;
}
else {
return chat.replace(a, b)
}
}
const fixAll = (chat, a, b) => {
let test = chat
while (test .includes (a)) {
test = fix (test, a, b)
}
return test
}
const chat = "This document ahs a typo in it. The other one ahs too.";
console .log (chat)
console .log (fixAll (chat, 'ahs', 'has'))
(请注意,我现在将字符串传递给函数。这使得代码更易于理解和测试,只使用它的参数,除了返回一个值之外什么都不做。这就是纯函数的定义。你会发现纯函数有很多优点。)
但其中有一些真正的冗余。我们没有充分的理由检查两次是否包含该字符串。fix
这可以通过将相关工作从into内联来清理fixAll
:
const fixAll = (chat, a, b) => {
let test = chat
while (test .includes (a)) {
test = test .replace (a, b)
}
return test
}
const chat = "This document ahs a typo in it. The other one ahs too.";
console .log (chat)
console .log (fixAll (chat, 'ahs', 'has'))
这是解决此问题的完全合理的方法。大概您的课程是关于教您一种替代技术,即使用递归来解决问题。所以让我们重新开始。
问:我们想做什么?
A:用正确的字符串替换所有出现的错字。
问:我们应该怎么做?
答:你什么意思?
问:嗯,我们首先应该做什么?
A:我猜是替换第一个。
问:我们如何做到这一点?
A:
string .replace (oldPart, newPart)
问:接下来是什么?
A:嗯,那我们换第二个。
问:如何?
答:同理,
string .replace (oldPart, newPart)
问:然后呢?
- 答:第三个,同样的方式。
问:然后呢?
答:嗯,我们一直这样做,直到不再有拼写错误。
问:我们怎么知道没有?
答:我们与
string .includes (oldPart)
问:我们什么时候做这个测试?
- 答:更换前。
问:每次?
答:是的。
问:好的,那么。你能把它写成一组明确的说明吗?
答:来了
1. Check if the string has any misspellings 2. If not, return it as is 3. If so, replace it with the good string 4. Go back to step 1.
问:看起来不错。但是当您返回到第 1 步时,您使用什么字符串进行测试?
A:我们刚刚用正确的单词替换了拼写错误的单词。
问:那么我们如何将它写成一个函数呢?
答:这个怎么样?
const changeSpelling = (string, oldPart, newPart) => { if (!string .includes (oldPart)) { return string } string.replace (oldPart, newPart) // hmm, do it again here. But how? }
问:是的。现在你想再做一次。您已经有一个功能可以做到这一点;这就是你在写的。我们不能叫它吗?
A:但它不完整。
问:这一步就完成了。在这里再次调用该函数会是什么样子?
答:我想是这样的:
const changeSpelling = (string, oldPart, newPart) => { if (!string .includes (oldPart)) { return string } string .replace (oldPart, newPart) changeSpelling (string, oldPart, newPart) }
问:越来越近了,但最后我们会返回什么?
A:哦,对了,应该是
return changeSpelling (string, oldPart, newPart)
。问:正确,但是我们应该将什么字符串传递给它?
A:我们刚换的那个。
问:是的,但
.replace
不会更改您的字符串,它会创建一个包含替换的新字符串。A:哦,所以我们需要保存更改后的字符串。这个怎么样?
const changeSpelling = (string, oldPart, newPart) => { if (string .includes (oldPart) === false) { return string } const newString = string .replace (oldPart, newPart) return changeSpelling (newString, oldPart, newPart) }
问:看起来不错。它是否遵循我们提到的递归规则?
A:嗯,它至少有一个基本案例。另一个规则是什么?
问:递归案例必须朝着您的基本案例之一取得进展。
A:是的,由于我们已经替换了其中一个错别字,我们正朝着没有任何错别字的情况前进。所以是的。
问:我认为它会起作用。你满意吗?
答:我认为是的。你会这样做吗?
问:嗯,我非常喜欢使用表达式而不是控制语句,并且不分配不必要的临时变量,所以我的看起来有点不同。但基本的想法是一样的。
A:你能告诉我你会怎么做吗?
问:当然,我的看起来更像这样:
const changeSpelling = (oldPart, newPart) => (string) => string .includes (oldPart) ? changeSpelling (oldPart, newPart) (string .replace (oldPart, newPart)) : string
A:看起来很不一样。为什么说是一样的?
问:我认为这是另一天的教训。
推荐阅读
- python-3.x - 将行附加到磁盘上的 shapefile(不在内存中)?
- sql - 有没有办法在 SQL VIEW 中用 NULL 填充缺失的数据点?
- postgresql - 为什么我的postgresql插入语句中没有重复的主键出现重复的主键错误?
- python - 在 Python 中查找和替换正则表达式
- javascript - 使用 useState 条件渲染数组和过滤后的数组版本
- javascript - JS DOM:如何阻止点击事件触发?
- sql - 我有一个超级简单的存储过程,它给我带来了问题
- ios - 自定义 SHA256 哈希计算在除空字符串之外的任何内容上都失败
- python - 使用 Selenium 拒绝访问并添加用户代理
- python - 为 Pandas 系列中的重复项目添加索引