Javascript 将 Reduce、Map 和 Concat 与数组结合使用的嵌套函数
Javascript Nested Functions Using Combination of Reduce, Map and Concat with an Array
谁能给我解释一下这段代码是怎么来的:
const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
console.log(powerset(["dog", "pig"]));
return这个数组输出到控制台了吗?
0: []
1: ["dog"]
2: ["pig"]
3: (2) ["pig", "dog"]
length: 4
重点是从数组中获取元素,然后 return 这些元素的所有可能组合。我了解 reduce 函数、连接和映射,但我很难理解如何应用这些嵌套函数以及以什么顺序获得此输出。任何人都可以引导我了解每个 运行-through 函数发生了什么?
首先,将常量转化为函数:
function powerset(arr){
return arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]])
}
我们知道reduce
会循环遍历元素,放入累加器a
。同时,它也会对 v
做 'something' 的值。那么,让我们深入挖掘一下:
a.concat(a.map(r => [v].concat(r)))
在这里,它获取累加器并向其添加一个数组。但是数组是什么?这是:
a.map(r => [v].concat(r))
现在我们可以看到它获取了 a
的每个元素,并且基本上将值 v
压入其中。
向后工作,现在我们可以看到 a
开始为 [[]]
,然后与从 a.map(r => [v].concat(r))
输出的数组合并。这恰好是 arr
的第一个元素。所以,它变成了 [[], [first_element]]
.
重复此操作,我们可以看到每次它都获取一个元素,将其添加到累加器中的每个子数组,获取所有这些数组,然后将其添加回累加器。所以现在,您拥有所有包含示例元素 el
和不包含示例元素 el
的集合。重复,你有所有可能的组合。
将代码视为单独的函数可能会有所帮助:
function powerset(arr) {
const initial = [[]];
return arr.reduce(reduceFn, initial);
function reduceFn(accumulatedValue, item) {
// item will be "dog" or "pig"
// accumulatedValue will start as [[]] and be equal to the result of the previous call of reduceFn by .reduce()
const concatenatedAccumulation = accumulatedValue.map(function mapFn(e) {
return [item].concat(e) // i.e. [item, ...e]
});
return accumulatedValue.concat(concatenatedAccumulation);
}
}
arr.reduce
的执行看起来像这样(读作 call(): result
):
reduceFn(accumulatedValue = [[]], item = 'dog'): [[], ['dog']]
- accumulatedValue.map:
mapFn(e = []): [['dog']]
- return [项目].concat:
['dog'].concat([]): ['dog']
- return accumulatedValue.concat:
return [[]].concat([['pig']])
reduceFn(accumulatedValue = [[], ['dog']], item = 'pig'): [[], ['dog'], ['pig'], ['pig', 'dog']]
- accumulatedValue.map:
mapFn(e = [[], ['dog']]): [['pig'], ['pig', 'dog']]
- return [项目].concat:
['pig'].concat([]): ['pig']
- return [项目].concat:
['pig'].concat(['dog']): ['pig', 'dog']
- return accumulatedValue.concat:
return [[], ['dog']].concat([['pig'], ['pig', 'dog']])
已回答!这是原始代码,以及我对正在发生的事情的新理解:
const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
console.log(powerset(["dog", "pig"]));
1.) reduce 函数正在接受累加器 a
,它以我们的初始化器 [[]]
和数组 powerset
中的第一个值 v
开始, 即 dog
.
2.) 当我们通过 a
进行映射时,我们 r
的第一个值是带有子数组 [[]]
的空数组。当您执行 [dog].concat([[]])
时,您最终只会得到 [dog]
.
3.) 然后,你有 a.concat(dog)
,所以你最终得到 [[], [dog]]
。您的新累加器或 a
值现在是 [[], [dog]]
.
4.) reduce函数的下一个循环,累加器a
是[[], [dog]]
,v
是我们powerset
数组中的第二项,pig
.
5.) 再次映射到 a
。第一个循环将是 pig.concat([])
。你只会得到 [pig]
.
6.) 下一个循环将是 pig.concat([dog])
,所以你得到 [pig, dog]
.
7.) 现在,再次执行 a.concat
。因为我们的新 a
是 [[], [dog]]
,我们现在添加我们的两个新结果以获得 [[], [dog], [pig], [pig, dog]]
.
这就是我们最终得到“猪、狗”的所有不同组合的方式。
谁能给我解释一下这段代码是怎么来的:
const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
console.log(powerset(["dog", "pig"]));
return这个数组输出到控制台了吗?
0: []
1: ["dog"]
2: ["pig"]
3: (2) ["pig", "dog"]
length: 4
重点是从数组中获取元素,然后 return 这些元素的所有可能组合。我了解 reduce 函数、连接和映射,但我很难理解如何应用这些嵌套函数以及以什么顺序获得此输出。任何人都可以引导我了解每个 运行-through 函数发生了什么?
首先,将常量转化为函数:
function powerset(arr){
return arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]])
}
我们知道reduce
会循环遍历元素,放入累加器a
。同时,它也会对 v
做 'something' 的值。那么,让我们深入挖掘一下:
a.concat(a.map(r => [v].concat(r)))
在这里,它获取累加器并向其添加一个数组。但是数组是什么?这是:
a.map(r => [v].concat(r))
现在我们可以看到它获取了 a
的每个元素,并且基本上将值 v
压入其中。
向后工作,现在我们可以看到 a
开始为 [[]]
,然后与从 a.map(r => [v].concat(r))
输出的数组合并。这恰好是 arr
的第一个元素。所以,它变成了 [[], [first_element]]
.
重复此操作,我们可以看到每次它都获取一个元素,将其添加到累加器中的每个子数组,获取所有这些数组,然后将其添加回累加器。所以现在,您拥有所有包含示例元素 el
和不包含示例元素 el
的集合。重复,你有所有可能的组合。
将代码视为单独的函数可能会有所帮助:
function powerset(arr) {
const initial = [[]];
return arr.reduce(reduceFn, initial);
function reduceFn(accumulatedValue, item) {
// item will be "dog" or "pig"
// accumulatedValue will start as [[]] and be equal to the result of the previous call of reduceFn by .reduce()
const concatenatedAccumulation = accumulatedValue.map(function mapFn(e) {
return [item].concat(e) // i.e. [item, ...e]
});
return accumulatedValue.concat(concatenatedAccumulation);
}
}
arr.reduce
的执行看起来像这样(读作 call(): result
):
reduceFn(accumulatedValue = [[]], item = 'dog'): [[], ['dog']]
- accumulatedValue.map:
mapFn(e = []): [['dog']]
- return [项目].concat:
['dog'].concat([]): ['dog']
- return [项目].concat:
- return accumulatedValue.concat:
return [[]].concat([['pig']])
- accumulatedValue.map:
reduceFn(accumulatedValue = [[], ['dog']], item = 'pig'): [[], ['dog'], ['pig'], ['pig', 'dog']]
- accumulatedValue.map:
mapFn(e = [[], ['dog']]): [['pig'], ['pig', 'dog']]
- return [项目].concat:
['pig'].concat([]): ['pig']
- return [项目].concat:
['pig'].concat(['dog']): ['pig', 'dog']
- return [项目].concat:
- return accumulatedValue.concat:
return [[], ['dog']].concat([['pig'], ['pig', 'dog']])
- accumulatedValue.map:
已回答!这是原始代码,以及我对正在发生的事情的新理解:
const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
console.log(powerset(["dog", "pig"]));
1.) reduce 函数正在接受累加器 a
,它以我们的初始化器 [[]]
和数组 powerset
中的第一个值 v
开始, 即 dog
.
2.) 当我们通过 a
进行映射时,我们 r
的第一个值是带有子数组 [[]]
的空数组。当您执行 [dog].concat([[]])
时,您最终只会得到 [dog]
.
3.) 然后,你有 a.concat(dog)
,所以你最终得到 [[], [dog]]
。您的新累加器或 a
值现在是 [[], [dog]]
.
4.) reduce函数的下一个循环,累加器a
是[[], [dog]]
,v
是我们powerset
数组中的第二项,pig
.
5.) 再次映射到 a
。第一个循环将是 pig.concat([])
。你只会得到 [pig]
.
6.) 下一个循环将是 pig.concat([dog])
,所以你得到 [pig, dog]
.
7.) 现在,再次执行 a.concat
。因为我们的新 a
是 [[], [dog]]
,我们现在添加我们的两个新结果以获得 [[], [dog], [pig], [pig, dog]]
.
这就是我们最终得到“猪、狗”的所有不同组合的方式。