如何从属性值生成变体

时间:2016-08-01 21:13:43

标签: javascript algorithm

我必须使用属性值创建所有组合的数组。

属性/值对象:

let attributes = {
    color:    ['red', 'green', 'blue'],
    sizes:    ['sm', 'md', 'lg'],
    material: ['cotton', 'wool']
}

我需要制作一个包含所有可能组合的数组。

color    sizes     material
red      sm        cotton
red      sm        wool
red      md        cotton
red      md        wool
red      lg        cotton
red      lg        wool
blue     sm        cotton
blue     sm        wool
blue     md        cotton
blue     md        wool
blue     lg        cotton
blue     lg        wool
green    sm        cotton
green    sm        wool
green    md        cotton
green    md        wool
green    lg        cotton
green    lg        wool

属性类型和值计数都是不确定的(至少为1)。我怎样才能做到这一点?

这是我到目前为止的代码

// keys = ['color', 'sizes', 'material']
// attributes is the same as above.

for (let keysIndex = 0; keysIndex < keys.length; keysIndex++) {
    let key = keys[i];
    let values = attributes[key];

    //loop through each value
    for (let valuesIndex = 0; valuesIndex < values.length; valuesIndex++) {

        // for each value, loop through all keys
        for (let keysIndex2 = 0; keysIndex2 < keys.length; keysIndex2++) {
            if (keysIndex === keysIndex2) {
                continue;
            }

            for (let valuesIndex2 = 0; valuesIndex2 < values.length; valuesIndex2++) {

                // What do I do from here?
                // Not sure if this is even the right path?

            }

        }

    }

}

1 个答案:

答案 0 :(得分:1)

我采取了两步法......首先,我从attributes对象中提取了一个数组数组([['red', 'green', 'blue'], ['sm', ...], ...])。然后我递归地计算了那些数组的乘积。然后我用适当的钥匙将它们放回物体中。

let attributes = {
    color:    ['red', 'green', 'blue'],
    sizes:    ['sm', 'md', 'lg'],
    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);

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

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

console.log(getAllCombinations(attributes));

// Output:
// [ { color: 'red', sizes: 'sm', material: 'cotton' },
//   { color: 'green', sizes: 'sm', material: 'cotton' },
//   { color: 'blue', sizes: 'sm', material: 'cotton' },
//   { color: 'red', sizes: 'md', material: 'cotton' },
//   { color: 'green', sizes: 'md', material: 'cotton' },
//   { color: 'blue', sizes: 'md', material: 'cotton' },
//   { color: 'red', sizes: 'lg', material: 'cotton' },
//   { color: 'green', sizes: 'lg', material: 'cotton' },
//   { color: 'blue', sizes: 'lg', material: 'cotton' },
//   { color: 'red', sizes: 'sm', material: 'wool' },
//   { color: 'green', sizes: 'sm', material: 'wool' },
//   { color: 'blue', sizes: 'sm', material: 'wool' },
//   { color: 'red', sizes: 'md', material: 'wool' },
//   { color: 'green', sizes: 'md', material: 'wool' },
//   { color: 'blue', sizes: 'md', material: 'wool' },
//   { color: 'red', sizes: 'lg', material: 'wool' },
//   { color: 'green', sizes: 'lg', material: 'wool' },
//   { color: 'blue', sizes: 'lg', material: 'wool' } ]