繁体   English   中英

尾递归减少函数返回[…,[Curcular]]

[英]Tail recursive reduce function returns […, [Curcular] ]

尝试编写一个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上下文的含义。 为什么会有这个问题,我将如何解决? 非常感谢您的宝贵时间!

考虑这一点的一种好方法是仅查看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 

为了弄清楚这里发生了什么,我们可以在您的递归函数中放置一个控制台日志,并使用如下这样的小集来运行它:

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,并将其添加到集合的末尾。 您可能想通过修改基本案例来解决这一问题。 我将其留给您练习,但是如果您需要更多帮助,可以随时提出反馈。

还有一个想法:

考虑到递归就像说函数的一次运行将负责一个动作/计算/步骤/无论您想考虑什么。 问问自己那一步是什么。

例如:

如果我是一个函数调用,也许我只想对以下问题负责:“我是否将当前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实际上是数组中的一个值,但希望它能说明这个概念。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM