How to Create a Hash or Dictionary Object in JavaScript

How to create a hash or dictionary object in JavaScript

Don't use an array if you want named keys, use a plain object.

var a = {};
a["key1"] = "value1";
a["key2"] = "value2";

Then:

if ("key1" in a) {
// something
} else {
// something else
}

How to do associative array/hashing in JavaScript

Use JavaScript objects as associative arrays.

Associative Array: In simple words associative arrays use Strings instead of Integer numbers as index.

Create an object with

var dictionary = {};

JavaScript allows you to add properties to objects by using the following syntax:

Object.yourProperty = value;

An alternate syntax for the same is:

Object["yourProperty"] = value;

If you can, also create key-to-value object maps with the following syntax:

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

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

You can iterate through an associative array using the for..in loop construct as follows

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

How to create dictionary and add key value pairs dynamically in Javascript

var dict = []; // create an empty array

dict.push({
key: "keyName",
value: "the value"
});
// repeat this last part as needed to add more key/value pairs

Basically, you're creating an object literal with 2 properties (called key and value) and inserting it (using push()) into the array.


Edit: So almost 5 years later, this answer is getting downvotes because it's not creating an "normal" JS object literal (aka map, aka hash, aka dictionary).

It is however creating the structure that OP asked for (and which is illustrated in the other question linked to), which is an array of object literals, each with key and value properties. Don't ask me why that structure was required, but it's the one that was asked for.

But, but, if what you want in a plain JS object - and not the structure OP asked for - see tcll's answer, though the bracket notation is a bit cumbersome if you just have simple keys that are valid JS names. You can just do this:

// object literal with properties
var dict = {
key1: "value1",
key2: "value2"
// etc.
};

Or use regular dot-notation to set properties after creating an object:

// empty object literal with properties added afterward
var dict = {};
dict.key1 = "value1";
dict.key2 = "value2";
// etc.

You do want the bracket notation if you've got keys that have spaces in them, special characters, or things like that. E.g:

var dict = {};

// this obviously won't work
dict.some invalid key (for multiple reasons) = "value1";

// but this will
dict["some invalid key (for multiple reasons)"] = "value1";

You also want bracket notation if your keys are dynamic:

dict[firstName + " " + lastName] = "some value";

Note that keys (property names) are always strings, and non-string values will be coerced to a string when used as a key. E.g. a Date object gets converted to its string representation:

dict[new Date] = "today's value";

console.log(dict);
// => {
// "Sat Nov 04 2016 16:15:31 GMT-0700 (PDT)": "today's value"
// }

Note however that this doesn't necessarily "just work", as many objects will have a string representation like "[object Object]" which doesn't make for a non-unique key. So be wary of something like:

var objA = { a: 23 },
objB = { b: 42 };

dict[objA] = "value for objA";
dict[objB] = "value for objB";

console.log(dict);
// => { "[object Object]": "value for objB" }

Despite objA and objB being completely different and unique elements, they both have the same basic string representation: "[object Object]".

The reason Date doesn't behave like this is that the Date prototype has a custom toString method which overrides the default string representation. And you can do the same:

// a simple constructor with a toString prototypal method
function Foo() {
this.myRandomNumber = Math.random() * 1000 | 0;
}

Foo.prototype.toString = function () {
return "Foo instance #" + this.myRandomNumber;
};

dict[new Foo] = "some value";

console.log(dict);
// => {
// "Foo instance #712": "some value"
// }

(Note that since the above uses a random number, name collisions can still occur very easily. It's just to illustrate an implementation of toString.)

So when trying to use objects as keys, JS will use the object's own toString implementation, if any, or use the default string representation.

How is a JavaScript hash map implemented?

every javascript object is a simple hashmap which accepts a string or a Symbol as its key, so you could write your code as:

var map = {};
// add a item
map[key1] = value1;
// or remove it
delete map[key1];
// or determine whether a key exists
key1 in map;

javascript object is a real hashmap on its implementation, so the complexity on search is O(1), but there is no dedicated hashcode() function for javascript strings, it is implemented internally by javascript engine (V8, SpiderMonkey, JScript.dll, etc...)

2020 Update:

javascript today supports other datatypes as well: Map and WeakMap. They behave more closely as hash maps than traditional objects.

Javascript HashTable use Object key

Here is a proposal:

function HashTable() {
this.hashes = {};
}

HashTable.prototype = {
constructor: HashTable,

put: function( key, value ) {
this.hashes[ JSON.stringify( key ) ] = value;
},

get: function( key ) {
return this.hashes[ JSON.stringify( key ) ];
}
};

The API is exactly as shown in your question.

You can't play with the reference in js however (so two empty objects will look like the same to the hashtable), because you have no way to get it. See this answer for more details: How to get javascript object references or reference count?

Jsfiddle demo: http://jsfiddle.net/HKz3e/

However, for the unique side of things, you could play with the original objects, like in this way:

function HashTable() {
this.hashes = {},
this.id = 0;
}

HashTable.prototype = {
constructor: HashTable,

put: function( obj, value ) {
obj.id = this.id;
this.hashes[ this.id ] = value;
this.id++;
},

get: function( obj ) {
return this.hashes[ obj.id ];
}
};

Jsfiddle demo: http://jsfiddle.net/HKz3e/2/

This means that your objects need to have a property named id that you won't use elsewhere. If you want to have this property as non-enumerable, I suggest you take a look at defineProperty (it's not cross-browser however, even with ES5-Shim, it doesn't work in IE7).

It also means you are limited on the number of items you can store in this hashtable. Limited to 253, that is.

And now, the "it's not going to work anywhere" solution: use ES6 WeakMaps. They are done exactly for this purpose: having objects as keys. I suggest you read MDN for more information: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/WeakMap

It slightly differs from your API though (it's set and not put):

var myMap = new WeakMap(),
object1 = {},
object2 = {};

myMap.set( object1, 'value1' );
myMap.set( object2, 'value2' );

console.log( myMap.get( object1 ) ); // "value1"
console.log( myMap.get( object2 ) ); // "value2"

Jsfiddle demo with a weakmap shim: http://jsfiddle.net/Ralt/HKz3e/9/

However, weakmaps are implemented in FF and Chrome (only if you enable the "Experimental javascript features" flag in chrome however). There are shims available, like this one: https://gist.github.com/1269991. Use at your own risk.

You can also use Maps, they may more suit your needs, since you also need to store primitive values (strings) as keys. Doc, Shim.

String to Integer Object hashing in JavaScript

Write a function that turns the object into a string with the keys in a consistent order.

function objToKey(obj) {  Object.keys(obj).sort().map(k => `${k}:${obj[k]}`).join(',');}
var d1 = {a: 1, b: 2}, d2 = {b: 2, a: 1}, m = new Map();
m.set(objToKey(d1), "foo");console.log(m.get(objToKey(d2)));

Map vs Object in JavaScript

According to MDN:

A Map object can iterate its elements in insertion order - a for..of loop will return an array of [key, value] for each iteration.

and

Objects are similar to Maps in that both let you set keys to values,
retrieve those values, delete keys, and detect whether something is
stored at a key. Because of this, Objects have been used as Maps
historically; however, there are important differences between Objects
and Maps that make using a Map better.

An Object has a prototype, so there are default keys in the map.
However, this can be bypassed using map = Object.create(null). The
keys of an Object are Strings, where they can be any value for a Map.
You can get the size of a Map easily while you have to manually keep
track of size for an Object.

Map

The iterability-in-order is a feature that has long been wanted by developers, in part because it ensures the same performance in all browsers. So to me that's a big one.

The myMap.has(key) method will be especially handy, and also the myMap.size property.

__hash__ for javascript?

You mean using objects as keys, how do you make sure you access that key again?

The magic method is toString(). Turns out all objects in JS use string keys, and the toString() method is called if it's not a string.

http://jsfiddle.net/udsdT/1/

var objA = {
data: 'yay',
toString: function() {
return 'value_as_key';
}
};

var objB = {
data: 'some other totally data thing',
toString: function() {
return 'value_as_key';
}
}

var foo = {};
foo[objA] = 'abc';
foo[objB] = 'def';
foo['value_as_key'] = 'qwe';
foo.value_as_key = 'omg';

foo[objA]; // 'omg'
foo[objB]; // 'omg'
foo['value_as_key']; // 'omg'
foo.value_as_key; // 'omg'

​​​​​​Usually though, you really don't want to use whole objects as keys. Especially if you dont create your own toString() method, since the default toString() method on basic objects isn't exactly very awesome...

({a:123}).toString() // [object Object]
({b:456}).toString() // [object Object]

var foo = {};
foo[{a:123}] = 'wtf';
foo[{asdf:9876}]; // 'wtf'
foo['[object Object]']; // 'wtf


Related Topics



Leave a reply



Submit