Javascript 我需要一些帮助来理解这种方法的组合(reduce、concat和map)
我正在学习ES6,我正在努力学习这一行代码。我知道我正在失去一些东西,我只是不明白到底发生了什么 守则:Javascript 我需要一些帮助来理解这种方法的组合(reduce、concat和map),javascript,ecmascript-6,Javascript,Ecmascript 6,我正在学习ES6,我正在努力学习这一行代码。我知道我正在失去一些东西,我只是不明白到底发生了什么 守则: const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); console.log(powerset([1, 2, 3]));
const powerset = arr =>
arr.reduce((a, v) =>
a.concat(a.map(r =>
[v].concat(r))), [[]]);
console.log(powerset([1, 2, 3]));
输出:
[[], [1], [2], [2, 1], [3], [3, 1], [3, 2], [3, 2, 1]]
我在这里看到了什么
第一个concat
将在“主数组”中连接每个map
的返回,这个将r
的值与v
的值连接,我相信r
等于a
基于此,我的理解是(我知道我错了,但我不知道为什么),它应该是这样工作的:
在第一个“级别”a
是一个空数组,并且v
等于1,因此第一个值应该是[1]
,而不是[]
,因为r
正在与v
串联;在第二个“级别”a
等于1,而v
等于2,什么将返回[2,1]
,而在第三个“级别”中,返回将是[3,2,1]
,因为v
等于3,而a
将返回[2,1]
正如我之前所说,我知道我错了,但我就是看不出我在这里失去了什么。我做了研究,也做了很多实验,但都没有得到
这段代码到底是如何工作的?让我们先稍微修改一下格式:
arr.reduce(
(a, v) => a.concat(a.map(r => [v].concat(r))),
[[]]
)
因此,reduce
将[[]]
作为起始值,回调函数返回与其他内容连接的列表。到目前为止,返回值是[[],…]
是合理的,然后,它是附加了附加值的起始值
将三个值传递到powerset
,此reduce
过程将进行三次迭代
现在,每个回合都有什么连接到列表中
a.map(r => [v].concat(r))
a
是它开始并将返回的列表,v
是arr
中的当前值,该列表首先被传递到powerset
r
是当前a
中的每个值
因此,在第一次迭代中,a
是[[]]
,因此r
将是[]
一次,而v
是1
:
[[]].map(_ => [1].concat([]))
→ [[]].map(_ => [1]) // [1].concat([]) is [1]
→ [[1]]
因此,第一个map
操作返回[[1]]
:
(a, _) => a.concat([[1]])
→ (_, _) => [[], [1]]
因此,您确实看到了输出的开始。在下一次迭代中,a
是[[],[1]]
,v
是2
a .map(r => [v].concat(r))
→ [[], [1]].map(r => [2].concat(r)) // two mappings here:
→ [] → [2].concat([]) // [2]
→ [1] → [2].concat([1]) // [2, 1]
→ [[2], [2, 1]]
因此:
您可以自己计算第三次迭代。FWIW,即使是经验丰富的人也必须眯着眼睛才能计算出来……将它分成几个小部分,并计算出传递给每个嵌套函数的确切内容,以及该函数反过来产生的内容。试着将
console.log(“adding”,v,“to”,JSON.stringify(a))
在reduce
回调中,这会让你犯两个错误:a
从来都不是空数组(如果它是空数组,它就不会工作),它从[[]]
开始。r
是a
的元素,而第一个r
实际上是一个空数组。因为您从不替换初始值[]的第一个索引。concat只是将数组连接在一起。现在已经非常清楚了。非常感谢你。这让我发疯,哈哈。但看到你的解释,我相信我明白我现在失去了什么。事实上,这是两件事,我没有考虑a
的第一个索引中的空数组,也没有考虑应用map
时的整个数组,只考虑当前值。但现在一切都清楚了。再次感谢你。
(a, _) => a.concat([[2], [2, 1]])
→ (_, _) => [[], [1], [2], [2, 1]]