I have an array of objects with the following structure:
var varientSections = [
{
type: "frame",
values: ["black", "white", "wood"]
},
{
type: "finish",
values: ["matte", "glossy"]
}
];
I want to get the combination of the array values and create a new list with it. Right now, I am able to retrieve the combination from the nested array values using the method called getCombination(varientSections) . However, I do not know how to create a new list with the following structure:
var results = [
{
attributes: [
{
type: "frame",
value: "black"
},
{
type: "finish",
value: "matte"
}
]
},
{
attributes: [
{
type: "frame",
value: "black"
},
{
type: "finish",
value: "glossy"
}
]
},
{
attributes: [
{
type: "frame",
value: "white"
},
{
type: "finish",
value: "matte"
}
]
},
{
attributes: [
{
type: "frame",
value: "white"
},
{
type: "finish",
value: "glossy"
}
]
},
{
attributes: [
{
type: "frame",
value: "wood"
},
{
type: "finish",
value: "matte"
}
]
},
{
attributes: [
{
type: "frame",
value: "wood"
},
{
type: "finish",
value: "glossy"
}
]
}
];
Below is my code:
function getCombinations(arr) {
if (arr.length === 0) {
return [[]];
}
let [current, ...rest] = arr;
let combinations = getCombinations(rest);
var result = current.values.reduce(
(accumulator, currentValue) => [
...accumulator,
...combinations.map(c => [currentValue, ...c])
],
[]
);
console.log("result is ");
console.log(result);
return result;
}
let varientCombinations = getCombinations(varientSections);
console.log(varientCombinations);
let updatedVarientDetails = [];
varientSections.forEach((varientSection, index) => {
let type = varientSection.type;
varientCombinations.forEach(combination => {
let obj = [
{
type: type,
value: combination[index]
},
];
updatedVarientDetails.push(obj);
});
});
console.log(updatedVarientDetails);
You could get the cartesian product and give it later the wanted style. The names and values are taken form the handed over object.
The algorithm takes all key/value pairs and has a stric view to the values, that means if an array is found or an object, hence w && typeof w === "object"
, the actual part is taken an used for adding additional key/value pairs.
For example a small object with two properties
{ a: 1, b: [2, 3] }
yields
[
{ a: 1, b: 2 },
{ a: 1, b: 3 }
]
A bit more advanced object, like
{ a: 1, b: { c: { d: [2, 3], e: [4, 5] } } }
yields the same structure as given
[
{
a: 1,
b: {
c: { d: 2, e: 4 }
}
},
{
a: 1,
b: {
c: { d: 2, e: 5 }
}
},
{
a: 1,
b: {
c: { d: 3, e: 4 }
}
},
{
a: 1,
b: {
c: { d: 3, e: 5 }
}
}
]
Thant means, from any found sub object the cartesian product is taken and combined with the actual values.
const getCartesian = object => Object.entries(object).reduce( (r, [key, value]) => { let temp = []; r.forEach(s => (Array.isArray(value) ? value : [value]).forEach(w => (w && typeof w === "object" ? getCartesian(w) : [w]).forEach(x => temp.push({ ...s, [key]: x }) ) ) ); return temp; }, [{}] ), data = [{ type: "frame", value: ["black", "white", "wood"] }, { type: "finish", value: ["matte", "glossy"] }], result = getCartesian(data) .map(o => ({ attributes: Object.assign([], o).map(({ ...o }) => o) })); console.log(result); console.log(getCartesian({ a: 1, b: { c: { d: [2, 3], e: [4, 5] } } }));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could simplify it to this:
var variantSections = [ { type: "frame", values: ["black", "white", "wood"] }, { type: "finish", values: ["matte", "glossy"] } ]; // iterate through each variantSection and create objects like {"type": "frame", "value": "black"} var sections = variantSections.map(variant => { return variant.values.map(val => ({type: variant.type, value: val})) }); // then iterate through the two resulting arrays of objects, combining each into the attributes object you want var results = []; for (var i = 0; i < sections[0].length; i++) { for (var j = 0; j < sections[1].length; j++) { results.push({attributes: [sections[0][i], sections[1][j]]}); } } console.log(JSON.parse(JSON.stringify(results)));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.