I need to create a nested hierarchy of options. The options are keys on an array with several sub-options as nested objects.
I need to generate a nested hierarchy from this object.
Starting with an object like this:
const starterObject = {
id1: {
1: { value: "A" },
2: { value: "B" },
3: { value: "C" },
},
id2: {
1: { value: 10 },
2: { value: 20 },
},
};
I need to end up with an object of permutations like this:
const permutations2 = {
1: [{ value: "A" }, { value: 10 }],
2: [{ value: "A" }, { value: 20 }],
3: [{ value: "B" }, { value: 10 }],
4: [{ value: "B" }, { value: 20 }],
5: [{ value: "C" }, { value: 10 }],
6: [{ value: "C" }, { value: 20 }],
};
I tried something like this:
const starterObject = { id1: { 1: { value: "A" }, 2: { value: "B" }, 3: { value: "C" }, }, id2: { 1: { value: 10 }, 2: { value: 20 }, }, }; const permutationMatrix = []; Object.keys(starterObject["id1"]).forEach(key2 => Object.keys(starterObject["id2"]).forEach(key1 => permutationMatrix.push([ starterObject["id1"][key2], starterObject["id2"][key1], ]) ) ); console.log(permutationMatrix)
But the problem is that the keys are hardcoded. The actual object will have 1-5 keys (id1 - id5) and any number of nested objects.
I think this will require recursion, but I'm not sure how to proceed from here.
Reduce, entries, and values can help and there is no need for recursion.
const starterObject = { id1: { 1: { value: "A" }, 2: { value: "B" }, 3: { value: "C" }, }, id2: { 1: { value: 10 }, 2: { value: 20 }, }, id3: { 1: { value: 100 } } }; var entries = Object.entries(starterObject) var out = entries.reduce((arr, group) => { const itms = Object.values(group)[1] const vals = Object.values(itms) // if first time, set up the initial arrays with first set of data if (!arr.length) { return vals.map(v => [v]) } // after first one, we will just loop over the arrays // and start adding the next set of data to each one return arr.reduce((updated, curr) => { vals.forEach(val => { // make copy so we are not adding data to the reference const copy = curr.slice() copy.push(val) updated.push(copy) }) return updated }, []) }, []) console.log(JSON.stringify(out))
You could use recursion for this. Your input/output format is somewhat peculiar with its array-like objects, with keys starting at 1. So for that I would suggest a separate wrapper function, which only takes care of such format conversions.
I had a go at a functional approach, creating separate functions for each of the callbacks needed in the process:
const clone = o => ({...o}); const prefixer = item => arr => [item, ...arr].map(clone); const merger = arr => item => arr.map(prefixer(item)); const extender = group => res => group.flatMap(merger(res)); // The recursive function based on standard array format const cross = (group, ...rest) => group ? extender(group)(cross(...rest)) : [[]]; // For dealing with the unconventional input/output format: const baseOne = (x, i) => [i+1, x]; const generatePermutations = obj => Object.fromEntries(cross(...Object.values(obj).map(Object.values)).map(baseOne)); // Sample data & call const starterObject = { id1: { 1: { value: "A" }, 2: { value: "B" }, 3: { value: "C" }, }, id2: { 1: { value: 10 }, 2: { value: 20 }, }, }; const permutations = generatePermutations(starterObject); console.log(permutations);
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.