如何基于对象各数组属性的所有值组合生成指定结构的对象数组?
问题背景
我当前有如下结构的对象:
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)
实现方案
你现有代码的问题在于逻辑仅遍历了每个属性的单独取值,没有做跨属性的取值组合,最终只会生成包含单个属性的对象数组,无法得到多属性的组合结果。
这个需求本质是计算对象所有属性对应数组的笛卡尔积,再将每个值组合映射为和原属性名对应的对象即可。考虑到你提到的数组元素量级较大,采用迭代式实现避免递归栈溢出风险,代码如下:
/** * 计算多个数组的笛卡尔积(迭代实现,兼容大数量级输入) * @param {any[][]} arrays 待计算的二维数组 * @returns {any[][]} 所有值组合的二维数组 */ function cartesianProduct(arrays) { return arrays.reduce( (accumulator, currentArray) => { return accumulator.flatMap(accItem => currentArray.map(currItem => [...accItem, currItem]) ) }, [[]] ) } /** * 将属性值为数组的对象转换为所有值组合的对象数组 * @param {Record<string, any[]>} inputObj 输入对象 * @returns {Record<string, any>[]} 所有值组合构成的数组 */ function transformToCombinationArray(inputObj) { const keys = Object.keys(inputObj) const valueList = keys.map(key => inputObj[key]) const allValueCombinations = cartesianProduct(valueList) return allValueCombinations.map(combo => { return Object.fromEntries( keys.map((key, index) => [key, combo[index]]) ) }) } // 调用示例 const inputObject = { object1: ["01", "02"], object2: ["item1", "item2", "item3"], object3: ["product1", "product2"] } const result = transformToCombinationArray(inputObject) console.log(result)
注意:你给出的目标结果中最后一项object1: "03"属于笔误,原输入object1数组中不存在该值,上述代码会严格基于输入的合法取值生成所有组合。
性能提示
笛卡尔积的总结果数是所有输入数组长度的乘积,如果单个数组长度达到数千,最终结果总量会极速膨胀(例如3个长度为1000的数组做笛卡尔积,结果总数为10亿条,会直接占满内存),实际使用前请先评估结果总规模,避免出现内存溢出问题。
内容的提问来源于stack exchange,提问作者Alejandro Valladares
相关产品推荐
相关产品推荐

