I want to be able to sort the nested object below from the lowest number to the high number...
{
"a": 50,
"b": {
"c": {
"d": 69,
"e": 420,
"f": 21,
"g": {
"h": 5,
"i": 3,
}
}
},
"j": 1,
"k": 1000
}
... so that it can look like this:
{
"j": 1, // min in OBJECT
"b": {
"c": { // min in B
"g": { // min in C
"i": 3, // min in G
"h": 5
},
"f": 21,
"d": 69,
"e": 420
}
},
"a": 50,
"k": 1000
}
Note that the object is sorted by the lowest number inside objects, meaning the object's direct children's values are [1, 3, 50, 1000].
CodePudding user response:
Quick and dirty using Object.entries, Array forEach, Array reduce and Array sort
getpaths
creates an array in the form
[
["a.b.c", 2],
["d.e", 1],
....
]
Which can then be sorted easily using Array sort
createPath
takes a root object, a path and a value and creates the "path" in the object
so, given {}, "a.b.c", 2
would result in
{
a: {
b: {
c: 2
}
}
}
Since (non numeric) object keys are "sorted" in insertion order, inserting the values in value order produces the object as required
let obj = { a: 50, b: { c: { d: 69, e: 420, f: 21, g: { h: 5, i: 3, }, }, }, j: 1, k: 1000 };
const getpaths = (obj) => {
const paths = [];
const fn = (obj, path = "") => {
Object.entries(obj).forEach(([key, value]) => {
if (typeof value === "object") {
return fn(value, `${path}.${key}`);
}
paths.push([`${path}.${key}`.slice(1), value]);
});
};
fn(obj);
return paths;
};
const createPath = (obj, [path, value]) => {
path.split(".").reduce(
(acc, key, index, array) => acc[key] ||= array[index 1] ? {} : value, obj);
return obj;
};
const result = getpaths(obj)
.sort(([, a], [, b]) => a - b)
.reduce((acc, item) => createPath(acc, item), {});
console.log(JSON.stringify(result, null, 4));