1

iam trying to create a list of products varinats from a list of selected options and options values i have data looks like this :

[
  {
   option: "size",
   selected_values: [{id: 1, value: "XL"}, {id: 2, value: "M"}]
  },
  {
   option: "color",
   selected_values: [{id: 14, value: "Red"}, {id: 15, value: "Blue"}]
  }
]

and from this data i want t create somthing like this :

[
 {
 varint_name: "XL Red",
 selected_values: [1, 14]
 },
 {
 varint_name: "XL Blue",
 selected_values: [1, 15]
 },
 {
 varint_name: "M Red",
 selected_values: [2, 14]
 },
 {
 varint_name: "M Blue",
 selected_values: [3, 15]
 }
]

taking into considration that the list of selected options and options values (first list) can be more than two objects its binded to a from so can be more or less iam using vue btw and i know that the list i want should be a computed value but i want to know the logic to genrate the desired shape of list

1 Answers1

2

As suggested, you will need to generate the Cartesian product of all option values.

I added a third option to showcase that this works for any given number of options.

const options = [{
  option: "size",
  selected_values: [
    { id: 1, value: "XL" },
    { id: 2, value: "M" }
  ]
}, {
  option: "color",
  selected_values: [
    { id: 14, value: "Red" },
    { id: 15, value: "Blue" }
  ]
}, {
  option: "length",
  selected_values: [
    { id: 30, value: "Short" },
    { id: 31, value: "Long" }
  ]
}];

const main = () => {
  const product = cartesian(...options.map(o => o.selected_values))
    .map(values => ({
      variant_name: values.map(({ value }) => value).join(' '),
      selected_values: values.map(({ id }) => id),
    }));

  console.log(product);
};

const cartesian = (...args) => {
  const result = [];
  __cartesianHelper(result, [], 0, args);
  return result;
}

const __cartesianHelper = (result, curr, index, all) => {
  for (let j = 0, l = all[index].length; j < l; j++) {
    const copy = [...curr, all[index][j]];
    if (index === all.length - 1) result.push(copy);
    else __cartesianHelper(result, copy, index + 1, all);
  }
};

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

Expected Output

[{
  variant_name: "XL Red Short",
  selected_values: [1, 14, 30]
}, {
  variant_name: "XL Red Long",
  selected_values: [1, 14, 31]
}, {
  variant_name: "XL Blue Short",
  selected_values: [1, 15, 30]
}, {
  variant_name: "XL Blue Long",
  selected_values: [1, 15, 31]
}, {
  variant_name: "M Red Short",
  selected_values: [2, 14, 30]
}, {
  variant_name: "M Red Long",
  selected_values: [2, 14, 31]
}, {
  variant_name: "M Blue Short",
  selected_values: [3, 15, 30]
},  {
  variant_name: "M Blue Long",
  selected_values: [3, 15, 31]
}]
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132