Objects vs arrays in Javascript for key/value pairs

Solution 1:

Each solution has its use cases.

I think the first solution is good if you're trying to define a one-to-one relationship (such as a simple mapping), especially if you need to use the key as a lookup key.

The second solution feels the most robust to me in general, and I'd probably use it if I didn't need a fast lookup key:

  • It's self-describing, so you don't have to depend on anyone using people to know that the key is the id of the user.
  • Each object comes self-contained, which is better for passing the data elsewhere - instead of two parameters (id and name) you just pass around people.
  • This is a rare problem, but sometimes the key values may not be valid to use as keys. For example, I once wanted to map string conversions (e.g., ":" to ">"), but since ":" isn't a valid variable name I had to use the second method.
  • It's easily extensible, in case somewhere along the line you need to add more data to some (or all) users. (Sorry, I know about your "for argument's sake" but this is an important aspect.)

The third would be good if you need fast lookup time + some of the advantages listed above (passing the data around, self-describing). However, if you don't need the fast lookup time, it's a lot more cumbersome. Also, either way, you run the risk of error if the id in the object somehow varies from the id in people.

Solution 2:

Actually, there is a fourth option:

var people = ['Joe', 'Sam', 'Eve'];

since your values happen to be consecutive. (Of course, you'll have to add/subtract one --- or just put undefined as the first element).

Personally, I'd go with your (1) or (3), because those will be the quickest to look up someone by ID (O logn at worst). If you have to find id 3 in (2), you either can look it up by index (in which case my (4) is ok) or you have to search — O(n).

Clarification: I say O(logn) is the worst it could be because, AFAIK, and implementation could decide to use a balanced tree instead of a hash table. A hash table would be O(1), assuming minimal collisions.

Edit from nickf: I've since changed the example in the OP, so this answer may not make as much sense any more. Apologies.

Post-edit

Ok, post-edit, I'd pick option (3). It is extensible (easy to add new attributes), features fast lookups, and can be iterated as well. It also allows you to go from entry back to ID, should you need to.

Option (1) would be useful if (a) you need to save memory; (b) you never need to go from object back to id; (c) you will never extend the data stored (e.g., you can't add the person's last name)

Option (2) is good if you (a) need to preserve ordering; (b) need to iterate all elements; (c) do not need to look up elements by id, unless it is sorted by id (you can do a binary search in O(logn). Note, of course, if you need to keep it sorted then you'll pay a cost on insert.

Solution 3:

Assuming the data will never change, the first (single object) option is the best.

The simplicity of the structure means it's the quickest to parse, and in the case of small, seldom (or never) changing data sets such as this one, I can only imagine that it will be frequently executed - in which case minimal overhead is the way to go.