reco
reco

Reputation: 480

How can i get the key and value from an object without a for loop?

Is there a better way of getting key and value of an object? I am trying to do this without a for loop.

obj = { collection: 'foo' }

for key, value of obj
  console.log key, value

If an object has one key with one value I thought there could be a more efficient way of doing this. I could be wrong though.

Upvotes: 3

Views: 2306

Answers (1)

mu is too short
mu is too short

Reputation: 434755

If you only want to check if an object has exactly one key then you could use a short circuiting loop:

exactly_one = (obj) ->
    return false if(!obj)
    how_many = 0
    for own key of obj
        break if(++how_many == 2)
    how_many == 1

The basic idea is to use a for ... of (i.e. JavaScript's for ... in) loop to start counting the number of keys in the object. There are only three cases that we care about:

  1. There are fewer than one key (i.e. null or no keys). The initial null check and the how_many = 0 initialization take care of this.
  2. There is exactly one key. In this case the loop will make one pass and ++how_many will get hit once leaving how_many == 1.
  3. There are more than one keys. In this case the loop will only make two iterations due to the break. We know that we'll get a false result as soon as we've encountered the second key so there's no need to keep counting.

That will function will make at most two iterations of the loop. That's still a loop but there's no rule that forces you to run through the whole loop when you don't need to, you can always break out early.

Demo: http://jsfiddle.net/ambiguous/qsNMA/

Minor adjustments to the logic would give you "at most one", "at least one", etc.

If you weren't born a C programmer, then you could unroll the logic a little bit:

for own key of obj
    ++how_many
    break if(how_many == 2)

You could also write it as:

(break if(++how_many == 2)) for own key of obj

but that's pushing it IMO.

The own stuff just adds hasOwnProperty checks to avoid accidentally grabbing things from the prototype. You probably won't need that but since they really are out to get me, I prefer to err on the side of caution.

There's also Object.keys but that's not universally supported and it will have to build a whole array when you only care if its length will be 1 or not:

exactly_one = (obj) ->
    return false if(!obj)
    Object.keys(obj).length == 1

Demo: http://jsfiddle.net/ambiguous/aH8wA/

Upvotes: 2

Related Questions