[英]How to prevent a recursive function from re-initializing an accumulating variable?
这个函数是用JavaScript编写的,但我认为这个概念可以用其他一些编程语言实现。
function uniteUnique(arr) {
let seenBefore = []; //the accumulating array
for (let item of arguments) {
if (typeof (item) == "object") {
uniteUnique(...item);
}
else if (!seenBefore.includes(item)) {
seenBefore.push(item);
}
}
return seenBefore;
}
简而言之,该函数迭代它作为参数接收的数组,它可能包含或不包含其他数组本身。 任何这些数组的最深层包含int
值。 该函数返回一个包含所有int
(即嵌套数组中出现的那些)的数组,但它只返回一次int,即使它出现多次。
我的问题在于,每次递归返回到更高级别时,它再次初始化包含已保存的int
的数组,即函数需要返回的数组( seenBefore
),因此会破坏整个过程。 一方面,我必须在函数启动时初始化数组,但另一方面,它会多次初始化并丢失以前存储的值。
例如,如果我要运行该功能
uniteUnique([1, 3, [6, 3], 2], [5, 2, 1, 4], [2, 1]);
输出应该是
[1,3,6,2,5,4]
因为该函数必须按处理顺序返回它偶然发现的数字。 该函数实际上返回一个空数组,因为它在函数从递归的最顶层返回之前再次初始化。
我该如何绕过这个问题?
(PS:我知道这可以通过将累积数组从函数中拉出到另一个范围来“解决”,但这会导致其他问题,例如每次运行函数之前需要重新初始化累积数组它不止一次。)
你误认了你的问题。 每次调用uniteUnique()
都有一个单独的局部变量值seenBefore
- 在递归调用期间没有任何“初始化”。
你真正的问题是:
uniteUnique(...item);
丢弃该函数调用的结果,因此忽略任何嵌套数组的内容。 您需要在某处分配此函数的返回值并使用它。
您可能还想将此函数调用的条件更改为:
if (Array.isArray(item)) {
作为当前条件typeof item == "object"
将包括无法迭代的对象。
另一种可能性是将seenBefore
定义为空数组作为默认的第二个参数 ,它以递归方式传递给函数的每次调用:
function uniteUnique(arr, seenBefore = []) {
for (const item of arr) {
if (typeof (item) == "object") {
uniteUnique(item, seenBefore);
}
else if (!seenBefore.includes(item)) {
seenBefore.push(item);
}
}
return seenBefore;
}
uniteUnique(someArr);
请注意,这会将单个参数作为数组接受,而不是多个参数。
您可以使用嵌套函数,这样您每次都不需要重新初始化累积数组:
function uniteUnique(arr) {
function iterate(seenBefore, arr)
{
for (let item of arr) {
if (Array.isArray(item)) {
iterate(seenBefore, item);
}
else if (!seenBefore.includes(item)) {
seenBefore.push(item);
}
}
}
let result = []; // the accumulating array
iterate(result, arr);
return result ;
}
你实际上并不需要在这里使用arguments
和扩展运算符,因为你的函数需要一个数组,你可以简单地传递一个数组。
您可能还想使用Set
for seenBefore
,因为Array.prototype.includes
扫描数组,这是无效的。
以防万一:如果您可以使用最新的ES2019功能并且更喜欢简单,这也可以通过单线程实现:
const uniquesArray = [...new Set(nestedArray.flat(Infinity))];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.