尝试编写一个reduce函数,该函数将过滤掉所有重复项。我知道还有其他方法可以解决此问题,但是我正在尝试练习递归函数。
function addToSet(a, b) {
a.add(b);
return a;
}
let set = new Set;
function reduce([head, ...last], fn, init) {
if (head === undefined) return init;
return fn(fn(init, head), reduce(last, fn, init))
}
const a = reduce([1, 2, 4, 6, 4, 3, 1, 2, 5, 1, 3, 4, 5, 7, 7], addToSet, set)
console.log(a)
// in node this returns // Set { 1, 2, 4, 6, 3, 5, 7, [Circular] }
我读到循环意味着对象是自引用的?但是我不确定我完全理解Set上下文的含义。为什么会有这个问题,我将如何解决? 非常感谢您的宝贵时间!
答案 0 :(得分:2)
考虑这一点的一种好方法是仅查看addToSet
的返回值。每次返回传入的集合。现在查看reduce
的返回值。它返回刚建立的fn
的结果,总是返回集合。
因此,您将reduce
的结果传递到fn
的第二个参数中时,会将集合传递给第二个参数fn
,这会将集合添加到设置并给您一份圆形参考。
此:
return fn(fn(init, head), reduce(last, fn, init))
最终成为:
return fn(init, init)
解决起来并不难,因为没有真正的理由两次调用函数。您的基本情况将最终返回集合,因此您只需调用一次fn
并返回reduce
的结果即可。
function addToSet(a, b) {
a.add(b);
}
let set = new Set;
function reduce([head, ...last], fn, init) {
if (head === undefined) return init
fn(init, head)
return reduce(last, fn, init)
}
const a = reduce([1, 2, 4, 6, 4, 3, 1, 2, 5, 1, 3, 4, 5, 7, 7], addToSet, set)
console.log([...a]) // spreading because sets don't print here
答案 1 :(得分:1)
要弄清楚这里发生了什么,我们可以在您的递归函数中放置一个控制台日志,并使用如下这样的小集来运行它:
function addToSet(a, b) {
a.add(b);
return a;
}
let set = new Set;
function reduce([head, ...last], fn, init) {
console.log("head", head)
console.log("last", last)
console.log("init", init)
if (head === undefined) return init;
return fn(fn(init, head), reduce(last, fn, init))
}
const a = reduce([2, 4, 4], addToSet, set)
console.log(a)
我们得到此输出(请记住,最后一行是最后一次调用返回的内容)
如您所见,您最后一次在空数组上调用递归函数,然后在其中返回init,并将其添加到集合的末尾。您可能想通过修改基本案例来解决这一问题。我会把它留给您找出答案,但是如果您需要更多帮助,可以随时发表评论。
又有一个想法:
考虑递归就像说该函数的一次运行将负责一个动作/计算/步骤/无论您想如何考虑。问问自己那一步是什么。
Ex:
如果我是一个函数调用,也许我只想对以下问题负责:“我是否将当前的head
添加到init
?”
有很多方法可以做到这一点,但也许一种方法是说(用伪代码):
reduce([head, ...last], fn, init) {
is_base_case (where head is undefined)?
return // do nothing -- we don't want undefined to be in the set
otherwise
attempt to add head to init
reduce(...) // call the next reduce fn -- responsible for the next head
return init // init should either have the original set or the set + head
}
这并没有说明undefined实际上是数组中的一个值,但希望它能说明这个概念。