如何在其他对象数组的每个值上创建多个数组?

3

目前我有这个数组结构:

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}

我需要将它转换为:

const array = [
  {
    object1: "01",
    object2: "item1",
    object3: "product1",
  }, {
    object1: "02",
    object2: "item1",
    object3: "product1",
  }, {
    object1: "01",
    object2: "item2",
    object3: "product1",
  }, {
    object1: "01",
    object2: "item3",
    object3: "product1",
  }, {
    object1: "02",
    object2: "item2",
    object3: "product1",
  }, {
    object1: "02",
    object2: "item3",
    object3: "product1",
  }, {
    object1: "01",
    object2: "item1",
    object3: "product2",
  }, {
    object1: "02",
    object2: "item1",
    object3: "product2",
  }, {
    object1: "02",
    object2: "item2",
    object3: "product2",
  }, {
    object1: "03",
    object2: "item2",
    object3: "product2",
  },
]

基本上,我需要根据初始数组对象的每个组合创建一个新的数组,并且初始数组包含数千个项。

这是我目前的代码,但没有得到我所需的结构。

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}
const arr = []
Object.entries(object).forEach((element, i) => {
  element.forEach((innerElement, j) => {
    let _element = {[`${element[0]}`]:element[1][j]}
    arr.push(_element)
  })
});

console.log("map", arr)

有没有办法将数据转换为我需要的结构?提前感谢!


这个有帮助吗?结构几乎与你的相同:将具有数组属性的对象转换为对象数组 - Nick Parsons
嘿@NickParsons,我刚试了一下并稍微改了一下,但它只返回了我提到的初始数据中的2个对象。它正在根据位置生成一个新对象,就像这样:0:对象 object1:“01” object2:“item1” object3:“product1” 1:对象 object1:“02” object2:“item2” object3:“product2”而那不是我真正需要的。我正在尝试更改它,但有点困难。 - Alejandro Valladares
哦,我明白了,是的,你想要多个组合,所以这不是同一类型的问题。不过我认为下面的答案应该能帮到你。 - Nick Parsons
3个回答

2
我建议创建一个通用的解决方案,它将遍历模板对象可能的属性和值,并创建一个包含所有可能结果的数组。
我们将创建一个addPossibleValues()函数,以扩展模板对象中每个键的对象数组。每一轮都会通过相关属性数组的连续长度增加对象的数量。

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}

function addPossibleValues(arr, property, possibleValues) {
    return possibleValues.flatMap(v => { 
        return (arr.length ? arr: [{}]).map(x => { 
            return { ...x, [property]: v};
        })
    });
}

let result = [];
for(let key in object) {
    result = addPossibleValues(result, key, object[key]);
}

console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

您也可以使用 Array.reduce() 方法来实现此操作:

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}

function addPossibleValues(arr, property, possibleValues) {
    return possibleValues.flatMap(v => { 
        return (arr.length ? arr: [{}]).map(x => { 
            return { ...x, [property]: v};
        })
    });
}

let result = Object.keys(object).reduce((acc, key) => {
    return addPossibleValues(acc, key, object[key]);
}, []);
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }


2

想法

逐步生成原始对象中数组的交叉乘积:

  • 遍历原始对象的所有属性。

  • 考虑某个迭代。

  • 假设我们有一个在前面迭代中填充的临时数组

  • 对于存储为当前迭代属性cp的数组的每个值cv...

    • 取出中间结果数组中的每个对象
    • 克隆它
    • 添加一个属性cp到克隆的对象中,并用值cv填充它。
    • 将克隆体添加到结果数组中
  • 通过从结果数组中删除克隆操作的原件来结束迭代(现在这些原件已经过时,因为它们是少一个维度的交叉乘积)。

  • 使用单个空对象数组初始化while过程

代码

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}


let a_res = [{}];
for (s_key in object) {
    let n_currentCount = a_res.length
      ;
          
    object[s_key].forEach ( ps_item => {
        for (let i = 0; i < n_currentCount; i++) {
            let o_new = Object.assign({ [s_key]: ps_item }, a_res[i])
              ;
              
            a_res.push(o_new);
        }
    });

    a_res.splice(0, n_currentCount); // in situ
}
console.log(a_res);


有趣的方法,感谢@collapsar的见解! - Alejandro Valladares

1

首先,我必须为我的英语道歉。您可以使用3个嵌套的forEach。

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}

var arr = []

object.object3.forEach(o3 => 
  object.object2.forEach(o2 =>
    object.object1.forEach(o1 => 
      arr.push({object1: o1, object2: o2, object3: o3}))));
      
console.log(arr);

如果您想更改组合的顺序,请更改forEach的顺序。

这种解决方案的缺点是必须事先知道叉积的维度和属性名称。优点是它是最简单的方法... - collapsar
没错,对象可以拥有尽可能多的属性,所以,正如之前提到的,这是最简单的方法,但在这种情况下不是最好的。谢谢! - Alejandro Valladares
是的,我完全同意,折叠星方法更好。我也认为从学习的角度来看,最好先理解我的方法,因为它非常简单和具体。一旦我的方法完全被理解,再去理解折叠星方法,因为它是一个非常优雅的解决方案。 - Pablo A. Revert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接