22

This question is almost identical to How to efficiently count the number of keys/properties of an object in JavaScript?.

I want to know one extra piece of information: what is a "constant-time" way of determining the number of keys in an Object? I am mostly concerned with doing this in Node.JS, as most Objects on the browser aren't too large to be of great concern.

EDIT: It appears that Object.keys(obj).length returns in linear time O(n) in Google Chrome and in Node.JS (i.e. dependent on the number of keys in obj). Is there a better O(1) method?

I did some testing in Node.JS (source is below)

var tests = [10e3, 10e4, 10e5, 10e6]
for(j in tests) {
    var obj = {};
    for(i = 0; i < tests[j]; i++)
        obj[i] = i;
    console.time('test' + tests[j]);
    Object.keys(obj).length;
    console.timeEnd('test' + tests[j]);
}

For n = 10e3, 10e4, 10e5, 10e6... results are:

test10000: 5ms
test100000: 20ms
test1000000: 371ms
test10000000: 4009ms
Community
  • 1
  • 1
BMiner
  • 14,934
  • 11
  • 47
  • 52
  • Nope. I'm feeling lazy today... :/ Case of the Mondays, I suppose. – BMiner Oct 31 '11 at 16:36
  • 2
    I suspect that getting the ".length" from the result of calling "Object.keys()" is constant-time, but I also suspect that calling "Object.keys()" is linear in the number of properties. – Pointy Oct 31 '11 at 16:36
  • 1
    http://jsperf.com/object-keys-performance 100 times as many items in the object causes it to be 200 times as slow on Chrome. – pimvdb Oct 31 '11 at 16:40
  • Thanks, @pimvdb -- that's really sad news. :( Is there any constant-time key-counting method in Node.JS? – BMiner Oct 31 '11 at 16:43
  • @BMiner: Not directly I guess - but you could make a helper function that adds/removes/modifies items in the object and keeps track of the length when doing so. Then it's just a matter of fetching the stored length when you need it. – pimvdb Oct 31 '11 at 16:48
  • @BMiner you can keep count manually using proxies. But that creates overhead elsewhere. Yes `.length` is O(n) – Raynos Oct 31 '11 at 17:18
  • You could probably build a C++ module for this :D – thejh Oct 31 '11 at 18:45
  • I now see I stated 100 times as much, but in fact it's 1000 times as much that causes it to be 2000 times as slow. But it still means a non-constant time algorithm. – pimvdb Nov 01 '11 at 12:10
  • @pimvdb If it's 1000 or 10000000 times as much, it should not be noticeably slower at all. That's what constant time means. I like your suggestion about keeping track manually - That's what I'll do for my particular app... makes me sad, though – BMiner Nov 01 '11 at 13:54
  • @Raynos - you're saying the .length is also O(n)? Getting the length property of an Array? – BMiner Nov 01 '11 at 13:54
  • 1
    @BMiner sorry I meant Yes `Object.keys(o).length` is O(n). `.length` on an array is O(1). – Raynos Nov 01 '11 at 14:25

3 Answers3

7

After a bit of research, there is no way to determine the number of keys in a JavaScript Object in constant time, at least not in Node... and not quite yet. Node internally keeps track of this information, but it does not expose it, since there is no method to do so in ECMA-262 5th.

It's worth noting that Harmony (ECMA version 6) may natively support Maps and Sets. Not sure what the spec for these will turn out to be.

I am told that we need to bring this up with TC39 committee.

Bug report for V8: http://code.google.com/p/v8/issues/detail?id=1800

BMiner
  • 14,934
  • 11
  • 47
  • 52
2

ECMA 6 harmony introduces Map and Set classes which you can probably utilize (in the future :)

var map = new Map;
map.set('a', 'b');
console.log(map.size); // prints 1

I believe it should have complexity O(1), not tried though. You can run it in node 0.11+ via node --harmony script.js.


Another way is to use Proxy class which also has been added in harmony.

deadrunk
  • 12,675
  • 4
  • 27
  • 29
-1

See the source, specifically GetLocalElementKeys

v8 objects.cc

Andrew
  • 13,367
  • 12
  • 62
  • 79
  • I'm too lazy to do this. English, please. I'd gladly accept your answer. :P – BMiner Oct 31 '11 at 16:56
  • Depending on what the object contains they do different things, worst case seems to be doing 1 for loop through all the elements. – Andrew Oct 31 '11 at 17:23