views:

271

answers:

4

that's it, that's my question. thanks! -Morgan

+1  A: 

Are you talking about Javascript objects (JSON)?

The specification says that the keys should be strings http://json.org/ .

But the Javascript interpreter allows both {"key": "val"} and {key: "val"}

Luca Matteis
I'm wondering if I can have a structure that works like a map in java, where keys can be any object (even another array). It doesn't have to be declared in json, it can be declared like: myarray[myObject] = value.
morgancodes
How can the key be an object, it's an identifier... maybe it should be myarray[value] = myObject;
Luca Matteis
@sktrdie Imagine this: { [ 'some', 'object', 'as', 'key' ]: 'value' } Invalid JSON, of course, but the question is whether it's valid in JS.
ephemient
+1  A: 

My original answer was incorrect in some significant regards. Please use Christoph's answer instead.

chaos
Are you sure it doesn't stringify the key (k=""+foo)? When I run o={};o[{}]=0;for(k in o)alert(typeof(k)+":"+k); I get "string:[object Object]"
ephemient
JavaScript property names are always strings, even array indices are treated as strings! `foo[bar]` is the same as `foo[String(bar)]`
Christoph
Damn. Yeah, it's using the stringification. Sorry, morgancodes, I've misled you.
chaos
I'd like to delete the post, but it won't let me delete the accepted answer.
chaos
Chaos: Can't you edit the answer and write that it was incorrect?
some
Let's find out...
chaos
Chaos: If you want, you can make the word "answer" a link to http://stackoverflow.com/questions/512825/#513016
some
Good idea, thanks. :)
chaos
+5  A: 

There are no native associative arrays in JavaScript, only objects. Objects have properties. The names of properties are always strings: even the numeric indices of arrays will be converted to strings before the 'array magic' happens.

If you're looking for associative arrays with arbitrary keys, look here.

Christoph
A: 

I've implemented javascript HashMap which code can be obtained from http://github.com/lambder/HashMapJS/tree/master

The keys and values can be arbitrary javascript objects. There is no requirements on objects used as keys or values.

The mechanism is trivial. For every key there is generated unique id (per HashMap instance). That id is injected to the key object under high unlikely to collide field name ;)

That id is then used to keying in the underlying baking standard javascript association object.

Here is the code:

/*
 =====================================================================
 @license MIT
 @author Daniel Kwiecinski <[email protected]>
 @copyright 2009 Daniel Kwiecinski.
 @end
 =====================================================================
 */
var HashMap = function() {
  this.initialize();
}

HashMap.prototype = {
  hashkey_prefix: "<#HashMapHashkeyPerfix>",
  hashcode_field: "<#HashMapHashkeyPerfix>",

  initialize: function() {
    this.backing_hash = {};
    this.code = 0;
  },
  /*
   maps value to key returning previous assocciation
   */
  put: function(key, value) {
    var prev;
    if (key && value) {
      var hashCode = key[this.hashcode_field];
      if (hashCode) {
        prev = this.backing_hash[hashCode];
      } else {
        this.code += 1;
        hashCode = this.hashkey_prefix + this.code;
        key[this.hashcode_field] = hashCode;
      }
      this.backing_hash[hashCode] = value;
    }
    return prev;
  },
  /*
   returns value associated with given key
   */
  get: function(key) {
    var value;
    if (key) {
      var hashCode = key[this.hashcode_field];
      if (hashCode) {
        value = this.backing_hash[hashCode];
      }
    }
    return value;
  },
  /*
   deletes association by given key.
   Returns true if the assocciation existed, false otherwise
   */
  del: function(key) {
    var success = false;
    if (key) {
      var hashCode = key[this.hashcode_field];
      if (hashCode) {
        var prev = this.backing_hash[hashCode];
        this.backing_hash[hashCode] = undefined;
        if(prev !== undefined)
          success = true;
      }
    }
    return success;
  }
}

//// Usage

// creation

var my_map = new HashMap();

// insertion

var a_key = {};
var a_value = {struct: "structA"};
var b_key = {};
var b_value = {struct: "structB"};
var c_key = {};
var c_value = {struct: "structC"};

my_map.put(a_key, a_value);
my_map.put(b_key, b_value);
var prev_b = my_map.put(b_key, c_value);

// retrieval

if(my_map.get(a_key) !== a_value){
  throw("fail1")
}
if(my_map.get(b_key) !== c_value){
  throw("fail2")
}
if(prev_b !== b_value){
  throw("fail3")
}

// deletion

var a_existed = my_map.del(a_key);
var c_existed = my_map.del(c_key);
var a2_existed = my_map.del(a_key);

if(a_existed !== true){
  throw("fail4")
}
if(c_existed !== false){
  throw("fail5")
}
if(a2_existed !== false){
  throw("fail6")
}

Bon Appétit, Daniel Kwiecinski

Lambder