1

I'm trying to treat a JS object as a dictionary, and I want to use a pair of values (one literal value, one other object) as a single key, which I've been putting in array form, without success. The problem is that only the literal value is working to differentiate the keys, as the following snippet illustrates:

var dictionary = {};

var keyOne = { blah:1 };
var keyTwo = { blegh:2 };

var keyArrayOne = [keyOne, "label"];
var keyArrayTwo = [keyTwo, "label"];

dictionary[keyArrayOne] = "some data";

console.log(dictionary[keyArrayTwo]);    //Console returns 'some data'

I know I can use an array in place of my dictionary object, and just iterate through and compare, but was hoping to take advantage of the quicker look-up.

For more info, I won't know anything about the object that constitutes the first element of the key (it can be anything), but the second part is always a string.

Is there any way to achieve what I'm after?

hanenbro
  • 604
  • 7
  • 16
  • 1
    both arrays are ["objectObject","label"]. if you don't need to safely contains keys like "valueOf", "__proto__", etc, just use an object and Object.keys(obj) to get an array of keys when needed. – dandavis Aug 26 '13 at 20:39
  • Ah, thanks for your response. I'm with you on the object problem; the issue being my use of an object as any part of the key, rather than the array in particular. I'm just struggling with the Object.keys(obj) suggestion I'm afraid. Could you indicate how it might fit around the snippet I posted? Thanks. – hanenbro Aug 26 '13 at 20:54

1 Answers1

1

These might be helpful:

https://stackoverflow.com/a/10893426/1090464

https://stackoverflow.com/a/10908885/1090464

  • Keep in mind JSON.stringify won't work for circular objects. Also that method assumes JSON.stringify returns the object properties in the same order (see comments in the first link and https://stackoverflow.com/a/17459406/1090464).

  • The other method works if you're not concerned you're modifying the objects that are being passed in; and you will be doing the lookup using the exact same object instance, because using another instance with the same value won't work. Also, in your case the the get/put functions will be a bit different, maybe something like this:

    put: function(obj, label, value) {
        obj.__hash_id = this.nextId();
        this.hash[[obj.__hash_id, label]] = value;
    }
    
    get: function(obj, label) {
        return this.hash[[obj.__hash_id, label]];
    }
    
  • Another approach could be to use the labels as keys, and let the value be an array of [objectPartOfKey, value], through which you search linearly (just like a bucket in a hash table). This might still be faster than linear search in an array of [label, object] pairs if the number of objects per label is "small" relative to the total number of objects.

That being said, you might want to measure the performance hit first before optimizing your original code to make sure it is worth it.

Community
  • 1
  • 1
emou
  • 189
  • 4
  • Good answer and ideas, thanks. There's a chance that, at some point, all properties of two key objects could be identical. And even though it's very unlikely to cause a conflict, adding a key property onto the key objects feels a little dirty :D The key/array combo sounds like the best compromise for speed and cleanliness, so I'll weigh that up against the full-blown array method, and compare the performance vs. implementation tidiness. – hanenbro Aug 27 '13 at 18:20