2009-02-04 20 views

Respuesta

1

¿Estás hablando de objetos Javascript (JSON)?

La especificación dice que las claves deben ser cadenas http://json.org/.

Pero el intérprete de JavaScript permite a la vez {"key": "val"} y {key: "val"}

+0

Me pregunto si puedo tener una estructura que funciona como un mapa en Java, donde las claves pueden ser cualquier objeto (incluso otra matriz). No tiene que declararse en json, se puede declarar como: myarray [myObject] = value. – morgancodes

+0

¿Cómo puede la clave ser un objeto, es un identificador ... tal vez debería ser myarray [value] = myObject; –

+1

@sktrdie Imagine esto: {['algo', 'objeto', 'como', 'clave']: 'valor'} JSON inválido, por supuesto, pero la pregunta es si es válido en JS. – ephemient

16

No hay matrices asociativas nativas en JavaScript, sólo los objetos. Los objetos tienen propiedades. Los nombres de las propiedades son siempre cadenas: incluso los índices numéricos de las matrices will be converted to strings antes de que ocurra la 'magia de matriz'.

Si está buscando matrices asociativas con claves arbitrarias, look here.

2

he implementado Javascript HashMap qué código se puede obtener de http://github.com/lambder/HashMapJS/tree/master

Las claves y los valores pueden ser objetos JavaScript arbitrario. No hay requisitos sobre los objetos utilizados como claves o valores.

El mecanismo es trivial. Para cada clave, se genera una identificación única (por instancia de HashMap). Ese id. Se inyecta en el objeto clave bajo alto poco probable que colisione el nombre de campo;)

Esa id se utiliza luego para introducir el objeto de asociación JavaScript javascript subyacente.

Aquí está el código:

/* 
===================================================================== 
@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

0

Basándose en la idea de Lambder, he implementado una pequeña biblioteca de estructuras de datos.

Lo he probado un poco y todo parece funcionar.

También asigna automáticamente una identificación única a cada HashTable/HashSet que se utiliza para identificar de forma única la propiedad de la clave del objeto.

var DataStructure = {}; 

DataStructure.init = function(){ 
DataStructure.initHashables(); 
delete DataStructure.initHashables; 
} 

DataStructure.initHashables = function(){ 
var objectHashableIndexer = new DataStructure.Indexer(); 

DataStructure.Hashable = function(){ 
    var self = this; 

    // Constant 
    // 
    // 
    const ERROR_KEY_DOES_NOT_EXIST = "Key doesn't exists in Hashable when trying to pop. Associated Key Object and Hashable logged to console."; 
    const HASH_MAP_KEY_PROPERTY_BASE = "DATA_STRUCTURE_HASH_MAP_KEY_PROPERTY_"; 

    // Attributes 
    // 
    // 
    var tableNumber = objectHashableIndexer.getIndex(); 
    var tableKeyProperty = HASH_MAP_KEY_PROPERTY_BASE + tableNumber.toString(); 
    self.tableKeyProperty = tableKeyProperty; 
    var indexer = new DataStructure.Indexer(); 
    var data = {}; 
    self.data = data; 

    // Methods 
    // 
    // 
    self.getObjectKey = function(){ 
     return indexer.getIndex().toString(); 
    } 

    self.putBackObjectKey = function(index){ 
     indexer.putBackIndex(parseInt(index)); 
    } 

    var getObjectKey = self.getObjectKey; 
    var putBackObjectKey = self.putBackObjectKey; 

    self.exists = function(key){ 
     if (!(tableKeyProperty in key)) 
      return false; 

     var realKey = key[tableKeyProperty]; 

     if (!(realKey in data)) 
      return false; 

     return true; 
    } 

    self.pop = function(key){ 
     if (!self.exists(key)){ 
      console.log(key); 
      console.log(self); 
      throw ERROR_KEY_DOES_NOT_EXIST; 
     } 
     else{ 
      var realKey = key[tableKeyProperty]; 
      delete key[tableKeyProperty]; 
      delete data[realKey]; 
      putBackObjectKey(realKey); 
     } 
    } 

    self.destroy = function(){ 
     objectHashableIndexer.putBackIndex(tableNumber); 
     delete self; 
    } 

} 

/* 
    Class DataStructure.ObjectHashMap 
     Purpose: Provides a way to hash arbitrary objects to values. 

     Prototype Arguments: 

     Attributes: 

     Methods: 

     Notes: 
      Should call inherited method destroy() when done with table to preserve indexes 
*/ 
DataStructure.ObjectHashMap = function(){ 
    DataStructure.Hashable.call(this); 
    var self = this; 

    // Constant 
    // 
    // 
    const ERROR_KEY_EXISTS = "Key already exists in ObjectHashMap when trying to push. Associated Key Object and ObjectHashMap logged to console."; 
    const ERROR_KEY_DOES_NOT_EXIST = "Key doesn't exists in ObjectHashMap when trying to getValue. Associated Key Object and ObjectHashMap logged to console."; 

    // Attributes 
    // 
    // 

    var tableKeyProperty; 
    var data; 

    // Initialization 
    // 
    // 
    self.init = function(){ 
     self.privatize(); 
     delete self.privatize; 
    } 

    self.privatize = function(){ 
     tableKeyProperty = self.tableKeyProperty; 
     delete self.tableKeyProperty; 

     getObjectKey = self.getObjectKey; 
     delete self.getObjectKey; 

     putBackObjectKey = self.putBackObjectKey; 
     delete self.putBackObjectKey; 

     data = self.data; 
     delete self.data; 
    } 

    // Methods 
    // 
    // 
    var getObjectKey; 
    var putBackObjectKey; 

    self.push = function(key, value){ 
     if (self.exists(key)){ 
      console.log(key); 
      console.log(self); 
      throw ERROR_KEY_EXISTS; 
     } 
     else{ 
      var realKey = getObjectKey(); 
      key[tableKeyProperty] = realKey; 
      data[realKey] = value; 
     } 
    } 

    self.getValue = function(key){ 
     if(!self.exists(key)){ 
      console.log(key); 
      console.log(self); 
      throw ERROR_KEY_DOES_NOT_EXIST; 
     } 
     else{ 
      var realKey = key[tableKeyProperty]; 
      return data[realKey]; 
     } 
    } 

    self.init(); 
    delete self.init; 
} 

/* 
    Class DataStructure.ObjectHashSet 
     Purpose: Provides a way to store arbitrary objects and check that they exist. 

     Prototype Arguments: 

     Attributes: 

     Methods: 

     Notes: 
      Should call inherited method destroy() when done with table to preserve indexes 
*/ 
DataStructure.ObjectHashSet = function(){ 
    DataStructure.Hashable.call(this); 
    var self = this; 

    // Constant 
    // 
    // 
    const ERROR_KEY_EXISTS = "Key already exists in ObjectHashSet when trying to push. Associated Key Object and ObjectHashSet logged to console."; 
    const ERROR_KEY_DOES_NOT_EXIST = "Key doesn't exists in ObjectHashSet when trying to getValue. Associated Key Object and ObjectHashSet logged to console."; 

    // Attributes 
    // 
    // 

    var tableKeyProperty; 
    var data; 

    // Initialization 
    // 
    // 
    self.init = function(){ 
     self.privatize(); 
     delete self.privatize; 
    } 

    self.privatize = function(){ 
     tableKeyProperty = self.tableKeyProperty; 
     delete self.tableKeyProperty; 

     getObjectKey = self.getObjectKey; 
     delete self.getObjectKey; 

     putBackObjectKey = self.putBackObjectKey; 
     delete self.putBackObjectKey; 

     data = self.data; 
     delete self.data; 
    } 

    // Methods 
    // 
    // 
    var getObjectKey; 
    var putBackObjectKey; 

    self.push = function(key){ 
     if (self.exists(key)){ 
      console.log(key); 
      console.log(self); 
      throw ERROR_KEY_EXISTS; 
     } 
     else{ 
      var realKey = getObjectKey(); 
      key[tableKeyProperty] = realKey; 
      data[realKey] = ""; 
     } 
    } 

    self.init(); 
    delete self.init; 
} 

} 

DataStructure.Indexer = function(){ 
var self = this; 

// Constant 
// 
// 
const DEFAULT_SIZE = 1000; 

// Attributes 
// 
// 
var nextIndex = 0; 
var availableIndicies = 0; 
var freeIndicies = []; 

// Initialization 
// 
// 
self.init = function(){ 
    freeIndicies.length = DEFAULT_SIZE; 
} 

// Methods 
// 
// 
self.getIndex = function(){ 
    var index = 0; 

    if (availableIndicies === 0){ 
     index = nextIndex; 
     ++nextIndex; 
    } 
    else{ 
     --availableIndicies; 
     index = freeIndicies[availableIndicies]; 
    } 

    return index; 
} 

self.putBackIndex = function(index){ 
    if (availableIndicies === freeIndicies.length) 
     freeIndicies.push(index); 
    else 
     freeIndicies[availableIndicies] = index; 

    ++availableIndicies; 
} 

self.init(); 
delete self.init; 
} 

DataStructure.init(); 
delete DataStructure.init; 
Cuestiones relacionadas