前言
const a = [
{ id: "17" , caption: "颜色" , types: [ "黑" , "棕" ] } ,
{ id: "23" , caption: "材质" , types: [ "牛皮" ] } ,
{ id: "24" , caption: "尺码" , types: [ "40" , "41" , "42" ] } ,
] ;
[
{ '17' : '黑' , '23' : '牛皮' , '24' : '40' } ,
{ '17' : '黑' , '23' : '牛皮' , '24' : '41' } ,
{ '17' : '黑' , '23' : '牛皮' , '24' : '42' } ,
{ '17' : '棕' , '23' : '牛皮' , '24' : '40' } ,
{ '17' : '棕' , '23' : '牛皮' , '24' : '41' } ,
{ '17' : '棕' , '23' : '牛皮' , '24' : '42' }
]
思路
这题有点像sku的简版,因为不涉及数量上问题,只要给出所有可能即可。 这题还是有点难的,主要难点就在于需要多层的循环或者嵌套,导致不太好想。 由于types不确定,可以先把types和id做成一个对象,然后迭代对象数组,通过下一个循环迭代出所有可能。
let res = a. reduce ( ( prev, cur) => {
let stack = cur. types;
let arr = [ ]
while ( stack. length!== 0 ) {
let type= stack. shift ( )
let obj= { }
obj[ cur. id] = type
arr. push ( obj)
}
prev. push ( arr)
return prev
} , [ ] ) . reduce ( ( prev, cur) => {
let arr = [ ]
prev. forEach ( a => {
cur. forEach ( b=> {
arr. push ( { ... a, ... b} )
} )
} ) ;
return arr
} )
console. log ( res)
那么有没有可能一次reduce搞定?那么我们就试着倒推,如果最终结果是那个数组,那么上一次迭代的结果应该是什么? reduce是有prev与cur的,prev用来做累积,最终结果是在prev上,那么没有做最后一次迭代前,生成的数据应该要去除最后那个再去重:
[
{ '17' : '黑' , '23' : '牛皮' } ,
{ '17' : '棕' , '23' : '牛皮' }
]
[
{ '17' : '黑' } ,
{ '17' : '棕' }
]
这里第二个单个,所以看起来第一到第二的过程并不是很明白。 这里直接放答案:
let res = a. reduce ( ( prev, cur) => {
let stack = cur. types;
let arr = [ ] ;
while ( stack. length !== 0 ) {
let type = stack. shift ( ) ;
let obj = { } ;
obj[ cur. id] = type;
arr. push ( obj) ;
}
let sr = [ ] ;
if ( prev. length=== 0 ) {
sr. push ( ... arr)
} else {
for ( let i = 0 ; i < arr. length; i++ ) {
for ( let k = 0 ; k < prev. length; k++ ) {
sr. push ( { ... prev[ k] , ... arr[ i] } ) ;
}
}
}
prev= [ ... sr]
return prev;
} , [ ] ) ;
console. log ( res) ;
总结
reduce是个非常好用的函数,特别是在这种不确定要迭代多少次时候,甚至一个reduce就可以解决这种叠加问题。