最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Create product variants based on attributes - Stack Overflow

programmeradmin1浏览0评论

I am working on an eCommerce javascript app, and trying to create product variants based on attributes.

If a product has attributes:

Size: Small, Medium, Large

Color: Red, Blue

Material: Cotton, Wool

I want result like this [{color: "Red", sizes: "Small"}, {color: "Blue", sizes: "Small"}, {color: "Red", sizes: "Medium"}, {color: "Blue", sizes: "Medium"}, {color: "Red", sizes: "Large"}, {color: "Blue", sizes: "Large"}]

I've done this, but is there an easy way to do this?

Here is the code that I've done:

let attributes = {
  color: ['Red', 'Blue'],
  sizes: ['Small', 'Medium', 'Large'],
  material: ['Cotton', 'Wool']
};

let getProducts = (arrays) => {
  if (arrays.length === 0) {
    return [[]];
  }

  let results = [];
  getProducts(arrays.slice(1)).forEach((product) => {
    arrays[0].forEach((value) => {
      results.push([value].concat(product));
    });
  });

  return results;
};

let getAllCombinations = (attributes) => {
  let attributeNames = Object.keys(attributes);
  // console.log(attributeNames);

  let attributeValues = attributeNames.map((name) => attributes[name]);
  // console.log(attributeValues);

  return getProducts(attributeValues).map((product) => {
    obj = {};
    attributeNames.forEach((name, i) => {
      obj[name] = product[i];
    });
    return obj;
  });
};

let binations = getAllCombinations(attributes);

console.log(binations.length);
console.log(binations);

I am working on an eCommerce javascript app, and trying to create product variants based on attributes.

If a product has attributes:

Size: Small, Medium, Large

Color: Red, Blue

Material: Cotton, Wool

I want result like this [{color: "Red", sizes: "Small"}, {color: "Blue", sizes: "Small"}, {color: "Red", sizes: "Medium"}, {color: "Blue", sizes: "Medium"}, {color: "Red", sizes: "Large"}, {color: "Blue", sizes: "Large"}]

I've done this, but is there an easy way to do this?

Here is the code that I've done:

let attributes = {
  color: ['Red', 'Blue'],
  sizes: ['Small', 'Medium', 'Large'],
  material: ['Cotton', 'Wool']
};

let getProducts = (arrays) => {
  if (arrays.length === 0) {
    return [[]];
  }

  let results = [];
  getProducts(arrays.slice(1)).forEach((product) => {
    arrays[0].forEach((value) => {
      results.push([value].concat(product));
    });
  });

  return results;
};

let getAllCombinations = (attributes) => {
  let attributeNames = Object.keys(attributes);
  // console.log(attributeNames);

  let attributeValues = attributeNames.map((name) => attributes[name]);
  // console.log(attributeValues);

  return getProducts(attributeValues).map((product) => {
    obj = {};
    attributeNames.forEach((name, i) => {
      obj[name] = product[i];
    });
    return obj;
  });
};

let binations = getAllCombinations(attributes);

console.log(binations.length);
console.log(binations);

Share Improve this question edited Mar 7, 2021 at 21:27 Muhammad Taseen asked Mar 7, 2021 at 21:03 Muhammad TaseenMuhammad Taseen 5791 gold badge7 silver badges22 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

try this:

let attributes = {
  color: ['Red', 'Blue'],
  sizes: ['Small', 'Medium', 'Large'],
  material: ['Cotton', 'Wool'],
  gender: ['Men', 'Women'],
  type: ['Casual', 'Sport']
};


let attrs = [];

for (const [attr, values] of Object.entries(attributes))
  attrs.push(values.map(v => ({[attr]:v})));

attrs = attrs.reduce((a, b) => a.flatMap(d => b.map(e => ({...d, ...e}))));

console.log(attrs);

If you don't need to support ie directly you could use a bination of array.prototype.flatMap() and array.prototype.map().

    let attributes = {
      color: ["Red", "Blue"],
      sizes: ["Small", "Medium", "Large"],
    };

    const bo = attributes.color.flatMap((d) =>
      attributes.sizes.map((v) => ({ color: d, sizes: v }))
    );

    console.log(bo);

A more generic solution which uses cartesian product of arrays in vanilla JS could look like this.

 let attributes = {
    color: ['Red', 'Blue'],
    sizes: ['Small', 'Medium', 'Large'],
    material: ['Cotton', 'Wool']
  };

    const f = (a, b) => [].concat(...a.map(d => b.map(e => [].concat(d, e))));
    const cartesian = (a, b, ...c) => (b ? cartesian(f(a, b), ...c) : a);
  
  const resArr = cartesian(attributes.color, attributes.sizes, attributes.material);
   const resObj = resArr.map((x)=>({color:x[0], sizes:x[1], material: x[2]}))
  console.log(resObj);

发布评论

评论列表(0)

  1. 暂无评论