user2915962 user2915962 - 2 months ago 7
Javascript Question

Traversing an object and picking out key/value

Im trying to create arrays from an keys in an object. I might have an object in this structure:

$scope.myobj = {
'level1': {
'level1Sub1': {
'result': 'level1-level1Sub1-result'
},
'level1Sub2': {
'result': 'level1-level1Sub2-result'
}
},
'level2': {
'level2Sub1': {
'result': 'level2-level2Sub1-result'
},
'level2Sub2': {
'result': 'level2-level2Sub2-result'
}
}
}


Elements on the same level goes in the same array.
So in this case the result should be:

TopLevelArr = [level1, level2]

SecondLevelArr = [level1Sub1, level1Sub2,level2Sub1,level2Sub2]


Im using jquery to traverse the whole object:

var path = "";

$.each($scope.myobj, walker);

function walker(key, value) {
var savepath = path;

path = path ? (path + "." + key) : key;
console.log(path)


if (value !== null && typeof value === "object") {
// Recurse into children
$.each(value, walker);
}

path = savepath;
}


This should be pretty close if I could find a way to pass the key into the proper array based on its level.

http://jsfiddle.net/bald1/ys05m1s8/2/

Help appreciated. Thank you.

Answer

You could use a iterative and recursive approach for getting all keys.

function getKeys(o) {
    function iter(o, i) {
        var k = Object.keys(o);
        keys[i] = keys[i] || [];
        k.forEach(function (kk) {
            if (keys[i].indexOf(kk) < 0) {
                keys[i].push(kk);
            }
            if (o[kk] !== null && typeof o[kk] === 'object') {
                iter(o[kk], i + 1);
            }
        });
    }

    var keys = [];
    iter(o, 0);
    return keys;
}

var $scope = {};
$scope.myobj = { 'level1': { 'level1Sub1': { 'result': 'level1-level1Sub1-result' }, 'level1Sub2': { 'result': 'level1-level1Sub2-result' } }, 'level2': { 'level2Sub1': { 'result': 'level2-level2Sub1-result' }, 'level2Sub2': { 'result': 'level2-level2Sub2-result' } } };

console.log(getKeys($scope.myobj));
.as-console-wrapper { max-height: 100% !important; top: 0; }