4
\$\begingroup\$

While responding to a SO question, I wrote the following method to convert a flat key structure to a hierarchical one as given below

In

{
 property1: 'value1',
 property2.property3: 'value2',
 property2.property7: 'value4',
 property4.property5.property6: 'value3',
}

Out

{
 property1: 'value1',
 property2: {
 property3: 'value2',
 property7: 'value4'
 },
 property4: {
 property5: {
 property6: 'value3'
 }
 }
}

Converter:

function convert(obj) {
 var res = {}, i, j, splits, ref, key;
 for (i in obj) {
 if (obj.hasOwnProperty(i)) {
 splits = i.split('.');
 ref = res;
 for (j = 0; j < splits.length; j++) {
 key = splits[j];
 if (j == splits.length - 1) {
 ref[key] = obj[i];
 } else {
 ref = ref[key] = ref[key] || {};
 }
 }
 };
 }
 return res;
}

Can this be improved?

Demo: Fiddle

asked Sep 26, 2013 at 3:04
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

The main complexity of this function arises from using a plain for-in loop to loop over object keys - this adds two extra indentation levels instead of just one level if one were to use a higher-level looping construct. So I would use some library function or create something like:

function eachKeyValue(obj, fun) {
 for (var i in obj) {
 if (obj.hasOwnProperty(i)) {
 fun(i, obj[i]);
 }
 }
}

Within this loop, there's another low-level for-loop, which I would again replace, say... with an Array.forEach method.

Now, in your code the loop goes over all the parts of the key, checking each time whether it's the last part. Instead of this, I would first remove the last part, loop over all the other parts to ensure all these are initialized, and then simply assign the value to the last position.

With some additional improvements to variable names, I would write it as such:

function convert(obj) {
 var result = {};
 eachKeyValue(obj, function(namespace, value) {
 var parts = namespace.split(".");
 var last = parts.pop();
 var node = result;
 parts.forEach(function(key) {
 node = node[key] = node[key] || {};
 });
 node[last] = value;
 });
 return result;
}

This code has just 2 levels of nesting compared to the original 4.

answered Sep 26, 2013 at 14:59
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.