Transform data from one shape to another in Javascript

时间:2018-07-24 10:24:12

标签: javascript ecmascript-6

How would I go about transforming this shape of data below using Javascript (es6 is fine).

From:

[
  {
    name: "Color",
    options: [{ value: "Gold" }, { value: "Space grey" }]
  },
  {
   name: "Size",
     options: [{ value: 32 }, { value: 64 }]
  },
  {
    name: "Width",
    options: [{ value: 100 }, { value: 200 }]
  }
]

To:

[
  {
    properties: {
      Color: "Gold",
      Size: 32,
      Width: 100
    }
  },
  {
    properties: {
      Color: "Gold",
      Size: 32,
      Width: 200
    }
  },
  {
    properties: {
      Color: "Gold",
      Size: 64,
      Width: 100
    }
  },
  {
    properties: {
      Color: "Gold",
      Size: 64,
      Width: 200
    }
  },
  {
    properties: {
      Color: "Space grey",
      Size: 32,
      Width: 100
    }
  },
  {
    properties: {
      Color: "Space grey",
      Size: 32,
      Width: 200
    }
  },
  {
    properties: {
      Color: "Space grey",
      Size: 64,
      Width: 100
    }
  },
  {
    properties: {
      Color: "Space grey",
      Size: 64,
      Width: 200
    }
  }
]

The second shape is every possible combination of options of the first shape.

I'm trying to build a product form that can handle products that have variants e.g. Color, Size, Material etc. Each of those variants can have multiple options. e.g. For Color, they could be Red, Blue, Orange etc. To get this to work I think I need to get a list that generates all possible combinations so that I can attach a price to each.

Would appreciate any help as I'm stumped :(

Below is what I tried. But its the wrong shape.

let variants = [{
    name: "Color",
    options: [{
      value: "Gold"
    }, {
      value: "Space grey"
    }]
  },
  {
    name: "Size",
    options: [{
      value: "32"
    }, {
      value: "64"
    }]
  },
  {
    name: "Width",
    options: [{
      value: "100"
    }, {
      value: "200"
    }]
  }
]

const [primaryOption, ...otherOptions] = variants

let options = []
primaryOption.options.map(x => {
  otherOptions.map(y => {
    y.options.map(z => {
      options = [
        ...options,
        {
          properties: {
            [primaryOption.name]: x.value,
            [y.name]: z.value
          }
        }
      ]
    })
  })
})

console.log(options)

3 个答案:

答案 0 :(得分:3)

 let result = [{}];

 for(const {name, options} of input) {
   const previous = result;
   result = [];
   for(const {value} of options) {
      for(const prev of previous)
         result.push({ ...prev, [name]: value });
   }
}

只需使用嵌套循环遍历所有值,并使用它们构建一个新数组即可。

答案 1 :(得分:0)

let variants = [{
    name: "Color",
    options: [{
      value: "Gold"
    }, {
      value: "Space grey"
    }]
  },
  {
    name: "Size",
    options: [{
      value: 32
    }, {
      value: 64
    }]
  },
  {
    name: "Width",
    options: [{
      value: 100
    }, {
      value: 200
    }]
  }
];

let endIndex = variants[0].options.length;
let result = [];

for (let i = 0; i < endIndex; i++) {
  variants.forEach(x => {
    result[i] = result[i] || {properties:{}};
    result[i].properties[x.name] = x.options[i].value;
  });
}

console.log(result);

答案 2 :(得分:0)

您可以通过迭代外部数组获取笛卡尔乘积,并获取内部数组以获取附加对象的值。

function getCartesian(array) {
    return array.reduce((r, { name, options }) => {
        var temp = [];
        r.forEach(({ property }) =>
            options.forEach(({ value }) => temp.push({ property: Object.assign({}, property, { [name]: value }) }))
        );
        return temp;
    }, [{}]);
}

var data = [{ name: "Color", options: [{ value: "Gold" }, { value: "Space grey" }] }, { name: "Size", options: [{ value: 32 }, { value: 64 }] }, { name: "Width", options: [{ value: 100 }, { value: 200 }] }];

console.log(getCartesian(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }