forEach/函数递归和返回值



那么我就有了一个像这样的数组

['id1/id2', 'id3', 'id4/id5/id6']

虽然它可能有超过3个条目,或者更多的分割值(/things) -这些可能会根据应用程序的状态而改变,但这是一个标准的例子。

我想输出:

[
['id1', 'id3', 'id4'],
['id1', 'id3', 'id5'],
['id1', 'id3', 'id6'],
['id2', 'id3', 'id4'],
['id2', 'id3', 'id5'],
['id2', 'id3', 'id6']
]

我认为forEach循环可以用来递归,但我被语法卡住了,所以尝试了一个标准的函数递归类型。我也不确定生成输出的返回过程。目前我得到的是:

singleOptionStemGenerator(route: string[]): [string[]] {
let returnArray: [string[]];
route.forEach((options: string) => {
// split into the various options
let splitOption: string[] = options.split('/');
splitOption.forEach((str: string) => {
if(route.length > 1) {
this.singleOptionStemGenerator(route.splice(0, 1));
} else {
return str;
}
})
});
return returnArray;
}

但是我不确定如何将ID值合并到一个新的数组中,然后将其添加到一个新的数组中。

编辑:下面给我的解决方案有点密集,所以我把它变成了一个函数,并对它进行了充分的注释。我还做了打字稿(我现在用的)。解决方案是所有的答案,这只是感觉清洁更容易阅读和学习:https://codepen.io/bogomip/pen/LYLjrxa

你所寻找的通常被称为笛卡尔积。有了计算这些的辅助函数,这就变得几乎微不足道了。

这里有一个版本:

const cartesian = ([xs, ...xss]) =>
xs = undefined
? []
: xss.length == 0
? xs .map (x => [x])
: xs .flatMap (x => cartesian (xss) .map (ys => [x, ...ys]))
const separate = (xs) => 
cartesian (xs .map (x => x .split ('/')))
console .log (separate (['id1/id2', 'id3', 'id4/id5/id6']))
.as-console-wrapper {max-height: 100% !important; top: 0}

更新注释清楚地表明这段代码有些密集。部分原因是我对纯表达式编码的偏好。对于那些更习惯于表达式和语句风格的Javascript的人来说,这个版本可能更熟悉:

const cartesian = (xss) => {
if (xss .length == 0) {
return []
}
const first = xss [0] 
const rest = xss .slice (1)
if (rest .length == 0) {
return first .map (x => [x])
}
const cartesianEnd = cartesian (rest)
return first .flatMap (
x => cartesianEnd .map (ys => [x, ...ys])
)
}

如果这种风格更符合您的喜好,那么它也可能有助于解释我编写的代码。除了……把它打出来让我意识到我的第一种方法效率很低。不幸的是,这个修复增加了一些复杂性,但显然是值得的:

const cartesian = ([xs, ...xss]) =>
xs = undefined
? []
: xss.length == 0
? xs .map (x => [x])
: ((yss = cartesian (xss)) => xs .flatMap (x => yss .map (ys => [x, ...ys]))) ()

问题是我正在重新计算当前数组中每个元素的剩余数组的乘积。这些不会改变,我们应该只做一次。啊,JS中真正的let绑定!我们可以用许多不同的方式来做这件事,但这一种还不错。

最新更新