Pergunta

Eu preciso armazenar algumas estatísticas usando JavaScript de uma forma como eu faria isso em C #:

Dictionary<string, int> statistics;

statistics["Foo"] = 10;
statistics["Goo"] = statistics["Goo"] + 1;
statistics.Add("Zoo", 1);

Existe uma Hashtable ou algo parecido Dictionary<TKey, TValue> em JavaScript?
Como eu poderia armazenar valores de tal maneira a?

Foi útil?

Solução

Use JavaScript objetos como arrays associativos .

array associativo:. Em palavras simples arrays associativos usar cordas em vez de números inteiros como índice

Criar um objeto com

var dictionary = {};

Javascript permite adicionar propriedades a objetos usando a seguinte sintaxe:

Object.yourProperty = value;

Uma sintaxe alternativa para o mesmo é:

Object["yourProperty"] = value;

Se você também pode criar chave para objeto de valor mapeia com a seguinte sintaxe

var point = { x:3, y:2 };

point["x"] // returns 3
point.y // returns 2

É possível percorrer uma matriz associativa usando a construção de laço for..in como se segue

for(var key in Object.keys(dict)){
  var value = dict[key];
  /* use key/value for intended purpose */
}

Outras dicas

var associativeArray = {};
associativeArray["one"] = "First";
associativeArray["two"] = "Second";
associativeArray["three"] = "Third";

Se você está vindo de uma linguagem orientada a objeto que você deve verificar este artigo .

A menos que você tenha um motivo específico para não, é só usar um objeto normal. As propriedades do objeto em JavaScript pode ser referenciado usando a sintaxe de estilo hashtable:

var hashtable = {};
hashtable.foo = "bar";
hashtable['bar'] = "foo";

Ambos os elementos foo e bar agora pode ser referenciado como:

hashtable['foo'];
hashtable['bar'];
// or
hashtable.foo;
hashtable.bar;

É claro que isso não significa suas chaves tem que ser strings. Se eles não são cordas que são convertidos internamente para cordas, por isso ainda pode funcionar, YMMV.

Todos os navegadores modernos suportam uma javascript Mapa objeto. Há um par de razões que tornam usando um mapa melhor do objeto:

  • Um objeto tem um protótipo, por isso há teclas padrão do mapa.
  • As chaves de um objeto são Cordas, onde eles podem ser qualquer valor para um mapa.
  • Você pode obter o tamanho de um mapa facilmente, enquanto você tem que manter o controle de tamanho de um objeto.

Exemplo:

var myMap = new Map();

var keyObj = {},
    keyFunc = function () {},
    keyString = "a string";

myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

myMap.size; // 3

myMap.get(keyString);    // "value associated with 'a string'"
myMap.get(keyObj);       // "value associated with keyObj"
myMap.get(keyFunc);      // "value associated with keyFunc"

Se você quiser as chaves que não são referenciados de outros objetos para ser lixo coletado, considere usar um WeakMap em vez de um mapa.

Uma vez que cada objeto na JS comporta-se como - e geralmente é implementado como - um hashtable, eu apenas ir com isso ...

var hashSweetHashTable = {};

-lo em C # os olhares código como:

Dictionary<string,int> dictionary = new Dictionary<string,int>();
dictionary.add("sample1", 1);
dictionary.add("sample2", 2);

ou

var dictionary = new Dictionary<string, int> {
    {"sample1", 1},
    {"sample2", 2}
};

em JavaScript

var dictionary = {
    "sample1": 1,
    "sample2": 2
}

objeto C # dicionário contém métodos úteis como dictionary.ContainsKey() em JavaScript que pode utilizar o hasOwnProperty como

if (dictionary.hasOwnProperty("sample1"))
    console.log("sample1 key found and its value is"+ dictionary["sample1"]);

Se você precisar de suas chaves para ser ser qualquer objeto em vez de apenas cordas, em seguida, você poderia usar o meu jshashtable .

Eu criei este para conseguir algum problema, tais como mapeamento de chave de objeto, a capacidade de enumeração (com método forEach()) e compensação.

function Hashtable() {
    this._map = new Map();
    this._indexes = new Map();
    this._keys = [];
    this._values = [];
    this.put = function(key, value) {
        var newKey = !this.containsKey(key);
        this._map.set(key, value);
        if (newKey) {
            this._indexes.set(key, this.length);
            this._keys.push(key);
            this._values.push(value);
        }
    };
    this.remove = function(key) {
        if (!this.containsKey(key))
            return;
        this._map.delete(key);
        var index = this._indexes.get(key);
        this._indexes.delete(key);
        this._keys.splice(index, 1);
        this._values.splice(index, 1);
    };
    this.indexOfKey = function(key) {
        return this._indexes.get(key);
    };
    this.indexOfValue = function(value) {
        return this._values.indexOf(value) != -1;
    };
    this.get = function(key) {
        return this._map.get(key);
    };
    this.entryAt = function(index) {
        var item = {};
        Object.defineProperty(item, "key", {
            value: this.keys[index],
            writable: false
        });
        Object.defineProperty(item, "value", {
            value: this.values[index],
            writable: false
        });
        return item;
    };
    this.clear = function() {
        var length = this.length;
        for (var i = 0; i < length; i++) {
            var key = this.keys[i];
            this._map.delete(key);
            this._indexes.delete(key);
        }
        this._keys.splice(0, length);
    };
    this.containsKey = function(key) {
        return this._map.has(key);
    };
    this.containsValue = function(value) {
        return this._values.indexOf(value) != -1;
    };
    this.forEach = function(iterator) {
        for (var i = 0; i < this.length; i++)
            iterator(this.keys[i], this.values[i], i);
    };
    Object.defineProperty(this, "length", {
        get: function() {
            return this._keys.length;
        }
    });
    Object.defineProperty(this, "keys", {
        get: function() {
            return this._keys;
        }
    });
    Object.defineProperty(this, "values", {
        get: function() {
            return this._values;
        }
    });
    Object.defineProperty(this, "entries", {
        get: function() {
            var entries = new Array(this.length);
            for (var i = 0; i < entries.length; i++)
                entries[i] = this.entryAt(i);
            return entries;
        }
    });
}


Documentação da classe Hashtable

Métodos:

  • get(key)
    Retorna o valor associado à chave especificada
    Parâmetros:.
    key: A chave a partir do qual recuperar o valor

  • .
  • put(key, value)
    Associates o valor especificado para a chave especificada
    Parâmetros:.
    key: A chave ao qual associar o valor
    . value:. O valor para associar à tecla

  • remove(key)
    Remove a chave especificada com o seu valor
    Parâmetros:.
    key:. A chave para remover

  • clear()
    Limpa todo o hashtable, removendo as chaves e valores.

  • indexOfKey(key)
    Retorna o índice da chave especificada, com base na ordem acrescentando
    Parâmetros:.
    key: A chave do que obter o índice

  • .
  • indexOfValue(value)
    Retorna o índice do valor especificado, com base na ordem acrescentando
    Parâmetros:.
    value: O valor dos quais obter o índice
    Notas:.
    Esta informação é obtida pelo método indexOf() de uma matriz, então ele compara objeto apenas com o método toString().

  • entryAt(index)
    Retorna um objeto com duas propriedades:. Chave e valor, representando a entrada no índice especificado
    Parâmetros:
    index:. O índice da entrada para obter

  • containsKey(key)
    Retorna se o hashtable contém a chave especificada
    Parâmetros:.
    key:. A chave para verificar

  • containsValue(value)
    Retorna se o hashtable contém o valor especificado
    Parâmetros:.
    value:. O valor para verificar

  • forEach(iterator)
    Repete todas as entradas na iterator especificado
    Parâmetros:.
    value: Um método com parâmetros: 3. key, value e index, onde index representa o índice da entrada

    Propriedades:

  • length ( Read-only )
    Obtém a contagem das entradas na tabela hash.

  • keys ( Read-only )
    Obtém uma matriz de todas as chaves na hashtable.

  • values ( Read-only )
    Obtém uma matriz de todos os valores na tabela hash.

  • entries ( Read-only )
    Obtém uma matriz de todas as entradas na tabela de dispersão. Eles são representados na mesma forma do entryAt() método.

function HashTable() {
    this.length = 0;
    this.items = new Array();
    for (var i = 0; i < arguments.length; i += 2) {
        if (typeof (arguments[i + 1]) != 'undefined') {
            this.items[arguments[i]] = arguments[i + 1];
            this.length++;
        }
    }

    this.removeItem = function (in_key) {
        var tmp_previous;
        if (typeof (this.items[in_key]) != 'undefined') {
            this.length--;
            var tmp_previous = this.items[in_key];
            delete this.items[in_key];
        }

        return tmp_previous;
    }

    this.getItem = function (in_key) {
        return this.items[in_key];
    }

    this.setItem = function (in_key, in_value) {
        var tmp_previous;
        if (typeof (in_value) != 'undefined') {
            if (typeof (this.items[in_key]) == 'undefined') {
                this.length++;
            } else {
                tmp_previous = this.items[in_key];
            }

            this.items[in_key] = in_value;
        }

        return tmp_previous;
    }

    this.hasItem = function (in_key) {
        return typeof (this.items[in_key]) != 'undefined';
    }

    this.clear = function () {
        for (var i in this.items) {
            delete this.items[i];
        }

        this.length = 0;
    }
}

https://gist.github.com/alexhawkins/f6329420f40e5cafa0a4

var HashTable = function() {
  this._storage = [];
  this._count = 0;
  this._limit = 8;
}


HashTable.prototype.insert = function(key, value) {
  //create an index for our storage location by passing it through our hashing function
  var index = this.hashFunc(key, this._limit);
  //retrieve the bucket at this particular index in our storage, if one exists
  //[[ [k,v], [k,v], [k,v] ] , [ [k,v], [k,v] ]  [ [k,v] ] ]
  var bucket = this._storage[index]
    //does a bucket exist or do we get undefined when trying to retrieve said index?
  if (!bucket) {
    //create the bucket
    var bucket = [];
    //insert the bucket into our hashTable
    this._storage[index] = bucket;
  }

  var override = false;
  //now iterate through our bucket to see if there are any conflicting
  //key value pairs within our bucket. If there are any, override them.
  for (var i = 0; i < bucket.length; i++) {
    var tuple = bucket[i];
    if (tuple[0] === key) {
      //overide value stored at this key
      tuple[1] = value;
      override = true;
    }
  }

  if (!override) {
    //create a new tuple in our bucket
    //note that this could either be the new empty bucket we created above
    //or a bucket with other tupules with keys that are different than 
    //the key of the tuple we are inserting. These tupules are in the same
    //bucket because their keys all equate to the same numeric index when
    //passing through our hash function.
    bucket.push([key, value]);
    this._count++
      //now that we've added our new key/val pair to our storage
      //let's check to see if we need to resize our storage
      if (this._count > this._limit * 0.75) {
        this.resize(this._limit * 2);
      }
  }
  return this;
};


HashTable.prototype.remove = function(key) {
  var index = this.hashFunc(key, this._limit);
  var bucket = this._storage[index];
  if (!bucket) {
    return null;
  }
  //iterate over the bucket
  for (var i = 0; i < bucket.length; i++) {
    var tuple = bucket[i];
    //check to see if key is inside bucket
    if (tuple[0] === key) {
      //if it is, get rid of this tuple
      bucket.splice(i, 1);
      this._count--;
      if (this._count < this._limit * 0.25) {
        this._resize(this._limit / 2);
      }
      return tuple[1];
    }
  }
};



HashTable.prototype.retrieve = function(key) {
  var index = this.hashFunc(key, this._limit);
  var bucket = this._storage[index];

  if (!bucket) {
    return null;
  }

  for (var i = 0; i < bucket.length; i++) {
    var tuple = bucket[i];
    if (tuple[0] === key) {
      return tuple[1];
    }
  }

  return null;
};


HashTable.prototype.hashFunc = function(str, max) {
  var hash = 0;
  for (var i = 0; i < str.length; i++) {
    var letter = str[i];
    hash = (hash << 5) + letter.charCodeAt(0);
    hash = (hash & hash) % max;
  }
  return hash;
};


HashTable.prototype.resize = function(newLimit) {
  var oldStorage = this._storage;

  this._limit = newLimit;
  this._count = 0;
  this._storage = [];

  oldStorage.forEach(function(bucket) {
    if (!bucket) {
      return;
    }
    for (var i = 0; i < bucket.length; i++) {
      var tuple = bucket[i];
      this.insert(tuple[0], tuple[1]);
    }
  }.bind(this));
};


HashTable.prototype.retrieveAll = function() {
  console.log(this._storage);
  //console.log(this._limit);
};

/******************************TESTS*******************************/

var hashT = new HashTable();

hashT.insert('Alex Hawkins', '510-599-1930');
//hashT.retrieve();
//[ , , , [ [ 'Alex Hawkins', '510-599-1930' ] ] ]
hashT.insert('Boo Radley', '520-589-1970');
//hashT.retrieve();
//[ , [ [ 'Boo Radley', '520-589-1970' ] ], , [ [ 'Alex Hawkins', '510-599-1930' ] ] ]
hashT.insert('Vance Carter', '120-589-1970').insert('Rick Mires', '520-589-1970').insert('Tom Bradey', '520-589-1970').insert('Biff Tanin', '520-589-1970');
//hashT.retrieveAll();
/* 
[ ,
  [ [ 'Boo Radley', '520-589-1970' ],
    [ 'Tom Bradey', '520-589-1970' ] ],
  ,
  [ [ 'Alex Hawkins', '510-599-1930' ],
    [ 'Rick Mires', '520-589-1970' ] ],
  ,
  ,
  [ [ 'Biff Tanin', '520-589-1970' ] ] ]
*/

//overide example (Phone Number Change)
//
hashT.insert('Rick Mires', '650-589-1970').insert('Tom Bradey', '818-589-1970').insert('Biff Tanin', '987-589-1970');
//hashT.retrieveAll();

/* 
[ ,
  [ [ 'Boo Radley', '520-589-1970' ],
    [ 'Tom Bradey', '818-589-1970' ] ],
  ,
  [ [ 'Alex Hawkins', '510-599-1930' ],
    [ 'Rick Mires', '650-589-1970' ] ],
  ,
  ,
  [ [ 'Biff Tanin', '987-589-1970' ] ] ]

*/

hashT.remove('Rick Mires');
hashT.remove('Tom Bradey');
//hashT.retrieveAll();

/* 
[ ,
  [ [ 'Boo Radley', '520-589-1970' ] ],
  ,
  [ [ 'Alex Hawkins', '510-599-1930' ] ],
  ,
  ,
  [ [ 'Biff Tanin', '987-589-1970' ] ] ]


*/

hashT.insert('Dick Mires', '650-589-1970').insert('Lam James', '818-589-1970').insert('Ricky Ticky Tavi', '987-589-1970');
hashT.retrieveAll();


/* NOTICE HOW HASH TABLE HAS NOW DOUBLED IN SIZE UPON REACHING 75% CAPACITY ie 6/8. It is now size 16.
 [,
  ,
  [ [ 'Vance Carter', '120-589-1970' ] ],
  [ [ 'Alex Hawkins', '510-599-1930' ],
    [ 'Dick Mires', '650-589-1970' ],
    [ 'Lam James', '818-589-1970' ] ],
  ,
  ,
  ,
  ,
  ,
  [ [ 'Boo Radley', '520-589-1970' ],
    [ 'Ricky Ticky Tavi', '987-589-1970' ] ],
  ,
  ,
  ,
  ,
  [ [ 'Biff Tanin', '987-589-1970' ] ] ]




*/
console.log(hashT.retrieve('Lam James'));  //818-589-1970
console.log(hashT.retrieve('Dick Mires')); //650-589-1970
console.log(hashT.retrieve('Ricky Ticky Tavi')); //987-589-1970
console.log(hashT.retrieve('Alex Hawkins')); //510-599-1930
console.log(hashT.retrieve('Lebron James')); //null

Você pode criar um usando como o seguinte:

var dictionary = { Name:"Some Programmer", Age:24, Job:"Writing Programs"  };

//Iterate Over using keys
for (var key in dictionary) {
  console.log("Key: " + key + " , " + "Value: "+ dictionary[key]);
}

//access a key using object notation:
console.log("Her Name is: " + dictionary.Name)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top