var object = {
aProperty: {
aSetting1: 1,
aSetting2: 2,
aSetting3: 3,
aSetting4: 4,
aSetting5: 5
},
bProperty: {
bSetting1: {
bPropertySubSetting : true
},
bSetting2: "bString"
},
cProperty: {
cSetting: "cString"
}
}
I need to loop through this object and build a list of the keys that shows the hierarchy, so the list ends up looking like this:aProperty.aSetting1
aProperty.aSetting2
aProperty.aSetting3
aProperty.aSetting4
aProperty.aSetting5
bProperty.bSetting1.bPropertySubSetting
bProperty.bSetting2
cProperty.cSetting
------------------
I made a FIDDLE for you. I am storing a stack
string and then output it, if the property is of primitive type:function iterate(obj, stack) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property], stack + '.' + property);
} else {
console.log(property + " " + obj[property]);
$('#output').append($("<div/>").text(stack + '.' + property))
}
}
}
}
iterate(object, '')
I have received a lot of upvotes for this question recently, so I've
decided to refine the solution with some ES2015+ magic and more
functional style.
It might be less readable, but I like how it looks :) You can still use a simpler solution from above - both of these should work exactly the same.
const isObject = val =>
typeof val === 'object' && !Array.isArray(val);
const paths = (obj = {}) =>
Object.entries(obj)
.reduce(
(product, [key, value]) =>
isObject(value) ?
product.concat([
[key, paths(value)] // adds [root, [children]] list
]) :
product.concat([key]), // adds [child] list
[]
)
const addDelimiter = (a, b) =>
a ? `${a}.${b}` : b;
const pathToString = ([root, children]) =>
children.map(
child =>
Array.isArray(child) ?
addDelimiter(root, pathToString(child)) :
addDelimiter(root, child)
)
.join('\n');
const input = {
aProperty: {
aSetting1: 1,
aSetting2: 2,
aSetting3: 3,
aSetting4: 4,
aSetting5: 5
},
bProperty: {
bSetting1: {
bPropertySubSetting: true
},
bSetting2: "bString"
},
cProperty: {
cSetting: "cString"
}
};
// ^ implies a "root" level will be ["", paths(input)]
// ideally paths() should return that structure, but I could not figure out how :)
// shows desired output format
console.log(pathToString(["", paths(input)]));
// showcase the resulting data structure
// any object can be recursively represented as a list [objectPropertyName, [...nestedPropertyNames]]
// console.log(paths(input));
No comments:
Post a Comment