首页 > 解决方案 > 尾递归 reduce 函数返回 [..., [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 的上下文中意味着什么。为什么我会遇到这个问题,我该如何解决?非常感谢你们的时间!

标签: javascriptnode.jsfunctionrecursioncircular-reference

解决方案


考虑这一点的一个好方法是只看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
  


推荐阅读