数组如何两两组合最后输出下面格式

const arr = [{
  "name": "color",
  "options": ["红色", "绿色"]
},
{
  "name": "size",
  "options": ["s", "m"]
}]

color和size 的key 从name 拿
如何两两组合最后输出下面格式,并希望能通用,比如3个数组的时候。

[{
 "price": '',
 "stock": '',
 "color": "红色",
 "size": "s"
},
{
 "price": '',
 "stock": '',
 "color": "红色",
 "size": "m"
},
{
 "price": '',
 "stock": '',
 "color": "绿色",
 "size": "s"
},
{
 "price": '',
 "stock": '',
 "color": "绿色",
 "size": "m"
}]
阅读 3.5k
4 个回答
[{
  "name": "color",
  "options": ["红色", "绿色"]
},
{
  "name": "size",
  "options": ["s", "m"]
},
{
  "name": "price",
  "options": ["1", "2"]
}].reduce(function(d, item){
    return d.reduce(function(c, citem){
        var so = JSON.stringify(citem)
        return c.concat(item.options.map(function(option){
            var o = JSON.parse(so)
            o[item.name] = option
            return o
        }))
    }, [])
}, [{}])

这个题目有点意思,我开始以为和矩阵乘法有点关系,准备用for循环,但是没那么简单,毕竟你这个可能有多个对象
理论上数组里面每增加一个特征对象,我这需要额外写一个for循环,但是程序肯定不能这么写
最后想到用递归,那么首先需要找联系以及结束条件
结束条件简单
当为数组里面有一个对象的时候,这么打出来就行了
怎么找联系呢,实际就是找这一次结果和上一次结果的关系,第二次明显在第一次的基础上每个对象加了一个属性,由于这个属性可能有两个值,所以之前的对象会编程现在的两个对象

// [{color:'红色'},{color: '绿色'}]  //数组里面一个对象的时候
//  [
//     {color: '红色',size: 'm'},    //数组里面两个对象的时候,注意联系
//     {color: '红色',size: 's'},
//     {color: '绿色',size: 'm'},
//     {color: '绿色',size: 's'}
//     ]

好了开始写程序,注意递归的写法,找联系,找结束条件

function rev(arr) { //接受一个数组
    let res = []
    if(arr.length === 1){ //结束条件
        let name = arr[0].name
        let options = arr[0].options
        options.forEach(option=>{
            let obj = {}
            obj[name] = option
            res.push(obj)
        })
    }else{
        //先得到新加入的特征对象,再建立和上一次结果的联系
        let newarr = arr.slice(0,-1)
        let name = arr.slice(-1)[0].name
        let options = arr.slice(-1)[0].options
        let oldres = rev(newarr) // 上一次的结果是一个数组,对数组进行再处理
        // 建立联系
        oldres.forEach(item=>{
            options.forEach(option=>{
                let obj = {}
                obj[name] = option
                res.push({...item,...obj})
            })

        })
    }
    return res
}

我们试一下

let res  = rev([{
    "name": "color",
    "options": ["红色", "绿色"]
},
    {
        "name": "size",
        "options": ["m", "z"]
    },
    {
        "name": "price",
        "options": ["1", "2"]
    }
])
console.log(res)
(8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {color: "红色", size: "m", price: "1"}
1: {color: "红色", size: "m", price: "2"}
2: {color: "红色", size: "z", price: "1"}
3: {color: "红色", size: "z", price: "2"}
4: {color: "绿色", size: "m", price: "1"}
5: {color: "绿色", size: "m", price: "2"}
6: {color: "绿色", size: "z", price: "1"}
7: {color: "绿色", size: "z", price: "2"}
length: 8

完美!

看起来只是一个排列组合吧。。。

function combination(list, lastResult = []) {
  if (!list.length) return lastResult
  let subItem = list.shift()
  if (!subItem.options.length) return lastResult
  if (!lastResult.length) {
    return combination(list, subItem.options.map(item => ({ [subItem.name]: item })))
  }
  
  let result = []
  for (let res of lastResult) {
    for (let item of subItem.options) {
      result.push({
        ...res,
        [subItem.name]: item
      })
    }
  }
  return combination(list, result)
}
let arr = [{
  "name": "color",
  "options": ["红色", "绿色"]
},
{
  "name": "size",
  "options": ["s", "m"]
},
{
  name: 'price',
  options: ['1', '2', '3']
}]

console.log(JSON.stringify(combination(arr)))
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题