简体   繁体   中英

Count keys in nested object

I am trying to get a tally of the keys in nested JS objects. I was able to get to the first level, but I'm a little stuck on how I would have it dig into the nested objects and return a count.

var properties = {
prop1: '',
prop2: '',
prop3: '',
prop4: {
    subProp1: '',
    subProp2: '',
    subProp3: {
        subSubprop1: ''
        }
    }
}

var getCount = function (data) {
var count = 0;
for (var k in data) {
    if (properties.hasOwnProperty(k)) {
        ++count;
    }
}
console.log( "this is the count for level 0: " + count //returns 4);
console.log( "this is the count for level 1: " + count //should return 3);
console.log( "this is the count for level 2: " + count //should return 1);
return count;
}
getCount(properties);

You can take a recursion, if the property is an object :

  var properties = { prop1: '', prop2: '', prop3: '', prop4: { subProp1: '', subProp2: '', subProp3: { subSubprop1: '' } } }, count = []; // i suggest to use named function for recursion, because the name is used // inside the function. otherwise it is not safe, if the name does not // match the given name at assignment function getCount(data, level) { level = level || 0; count[level] = count[level] || 0; for (var k in data) { data.hasOwnProperty(k) && count[level]++; typeof data[k] === 'object' && getCount(data[k], level + 1); } } getCount(properties); document.write('<pre>' + JSON.stringify(count, 0, 4) + '</pre>'); 

Bonus: A version with built in count in a functional style

 var properties = { prop1: '', prop2: '', prop3: '', prop4: { subProp1: '', subProp2: '', subProp3: { subSubprop1: '' } } }; function f(o, l, r) { l = l || 0; return Object.keys(o).reduce(function (r, k) { r[l] = (r[l] || 0) + 1; typeof o[k] === 'object' && f(o[k], l + 1, r); return r; }, r || []); } document.write('<pre>' + JSON.stringify(f(properties), 0, 4) + '</pre>'); 

This is a short and hacky way to do that:

var obj={a:0,b:1,c:{a:1,otherkeyb:'2:"":2\\',otherkey:{d:1,e:2}}}
JSON.stringify(obj).match(/[^\\]":/g).length // return 8

Break down

This another solution will create an array, that tell you how many items in each level

var count_in_level = []
var obj = {
    a: 0,
    b: {
        ba: 1,
        c: {
            ca: 1,
            cb: 2
        }
    }
}
function count(obj, level) {
    var c = 0
    if (typeof level == 'undefined') level = 1
    if (!count_in_level[level]) count_in_level[level] = 0
    if (typeof obj == 'object') {
        for (var i in obj) {
            if (typeof obj[i] == 'object') count(obj[i], level + 1)
            c++;
        }
        count_in_level[level] += c
    }
}
count(obj);
console.log(count_in_level)  // [1: 2, 2: 2, 3: 1]

Explain: Level 1: 2 items, level 2: 2 items, level 3: 1 item

How about using Object.keys (if available [eg not supported in IE < 9]) and storing the count in object, where the key is the level and the value is count?

var properties = {
    prop1: '',
    prop2: '',
    prop3: '',
    prop4: {
        subProp1: '',
        subProp2: '',
        subProp3: {
            subSubprop1: ''
        }
    }
};

function countKeysPerLevel(store, level, obj) {
    var keys = Object.keys(obj);
    var count = keys.length;

    store[level] = (store[level] || 0) + count;

    for (var i = 0; i < count; i++) {
        var childObj = obj[keys[i]];
        if (typeof childObj === 'object') {
            countKeysPerLevel(store, level + 1, childObj);
        }
    }
}

var result = {};
countKeysPerLevel(result, 0, properties);

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM