144

i need to make a dictionary in javascript like this

i dont remember the exact notation, but it was something like:

states_dictionary={ CT=[alex,harry], AK=[liza,alex], TX=[fred, harry] ........ }

is there such a thing in javascript?

Alex Gordon
  • 57,446
  • 287
  • 670
  • 1,062

7 Answers7

167

This is an old post, but I thought I should provide an illustrated answer anyway.

Use javascript's object notation. Like so:

states_dictionary={ 
     "CT":["alex","harry"], 
     "AK":["liza","alex"], 
     "TX":["fred", "harry"]
};

And to access the values:

states_dictionary.AK[0] //which is liza

or you can use javascript literal object notation, whereby the keys not require to be in quotes:

states_dictionary={ 
     CT:["alex","harry"], 
     AK:["liza","alex"], 
     TX:["fred", "harry"]
};
Peter
  • 2,172
  • 1
  • 15
  • 11
  • 16
    it's worth noting that the first example should yield the same object in both languages using exactly same syntax except the closing ';'. states_dictionary={ "CT":["alex","harry"], "AK":["liza","alex"], "TX":["fred", "harry"] } – Denis C Jul 01 '13 at 18:10
  • I am more used to the literal object notation, since you access them in the same way what is the difference between the two? – John Demetriou Jan 15 '15 at 15:34
  • 3
    @JohnDemetriou the main difference is javascript object notation keys must be strings (enclosed in double quotes " " ). The object notation is as seen in JSON for data interchage and was inspired by the literal object notation; it is worth noting that JSON is usually used in string context – Peter Jan 24 '15 at 17:53
  • 3
    Actually, Python allows statement-terminating semicolons, so the first example is completely valid both in Python and JavaScript – celticminstrel Oct 15 '15 at 22:45
  • 1
    If the value comes from the user, then care needs to be taken to use `Object.hasOwnProperty.call(dictionary, key)` (otherwise the user can enter a value of *valueOf* and `dictionary['valueOf']` returns the `Object.valueOf()` function belonging to the Object prototype which is probably not what your code would expect - potential bug or security issue). If the key is not a string type, then care needs to be taken, otherwise the implicit numeric and toString conversions will cause you problems. The ES6 `Map` type has been designed to provide extended functionality for dictionaries. – robocat Oct 04 '16 at 22:41
74

There were no real associative arrays in Javascript until 2015 (release of ECMAScript 6). Since then you can use the Map object as Robocat states. Look up the details in MDN. Example:

let map = new Map();
map.set('key', {'value1', 'value2'});
let values = map.get('key');

Without support for ES6 you can try using objects:

var x = new Object();
x["Key"] = "Value";

However with objects it is not possible to use typical array properties or methods like array.length. At least it is possible to access the "object-array" in a for-in-loop.

Alex
  • 5,240
  • 1
  • 31
  • 38
  • 3
    What about the performance? is looking up a key in an object constant time? – Saher Ahwal Oct 09 '11 at 02:04
  • 5
    Since o["key"] is equivalent to o.key in Javascript the performance is almost the same. However performance depends on the Javascript Engine / Webbrowser. There are quite a lot differences between these, especially in the older versions. – Alex Oct 13 '11 at 09:05
  • 1
    ECMAScript 6 defines an official Map object (i.e. "There are no real associative arrays in Javascript" is now incorrect). – robocat Oct 04 '16 at 22:29
39

In ECMAScript 6, the official Map object has been introduced, which is a dictionary implementation:

let dict = new Map();
dict.set("foo", "bar");

//returns "bar"
dict.get("foo");

Unlike javascript's normal objects, it allows any object as a key using identity comparison:

let foo = {};
let bar = {};
let dict = new Map();
dict.set(foo, "Foo");
dict.set(bar, "Bar");

//returns "Bar"
dict.get(bar);

//returns "Foo"
dict.get(foo);

//returns undefined, as {} !== foo and {} !== bar
dict.get({});

There is no way to have a user defined key comparator, so if you do not desire identity comparison, you are still stuck with only using number or string keys like with a normal object.

Old Badman Grey
  • 668
  • 10
  • 19
JimmyMcHoover
  • 764
  • 7
  • 15
  • 1
    Works for me, nice to use a cleaner ES6 method. Thank you! Follow up, de we know any way to "bulk set()", e.g. like python `dict = { key: value)`? – Joe Sadoski Aug 13 '20 at 05:14
11

Have created a simple dictionary in JS here:

function JSdict() {
    this.Keys = [];
    this.Values = [];
}

// Check if dictionary extensions aren't implemented yet.
// Returns value of a key
if (!JSdict.prototype.getVal) {
    JSdict.prototype.getVal = function (key) {
        if (key == null) {
            return "Key cannot be null";
        }
        for (var i = 0; i < this.Keys.length; i++) {
            if (this.Keys[i] == key) {
                return this.Values[i];
            }
        }
        return "Key not found!";
    }
}


// Check if dictionary extensions aren't implemented yet.
// Updates value of a key
if (!JSdict.prototype.update) {
    JSdict.prototype.update = function (key, val) {
        if (key == null || val == null) {
            return "Key or Value cannot be null";
        }
        // Verify dict integrity before each operation
        if (keysLength != valsLength) {
            return "Dictionary inconsistent. Keys length don't match values!";
        }
        var keysLength = this.Keys.length;
        var valsLength = this.Values.length;
        var flag = false;
        for (var i = 0; i < keysLength; i++) {
            if (this.Keys[i] == key) {
                this.Values[i] = val;
                flag = true;
                break;
            }
        }
        if (!flag) {
            return "Key does not exist";
        }
    }
}



// Check if dictionary extensions aren't implemented yet.
// Adds a unique key value pair
if (!JSdict.prototype.add) {
    JSdict.prototype.add = function (key, val) {
        // Allow only strings or numbers as keys
        if (typeof (key) == "number" || typeof (key) == "string") {
            if (key == null || val == null) {
                return "Key or Value cannot be null";
            }
            if (keysLength != valsLength) {
                return "Dictionary inconsistent. Keys length don't match values!";
            }
            var keysLength = this.Keys.length;
            var valsLength = this.Values.length;
            for (var i = 0; i < keysLength; i++) {
                if (this.Keys[i] == key) {
                    return "Duplicate keys not allowed!";
                }
            }
            this.Keys.push(key);
            this.Values.push(val);
        }
        else {
            return "Only number or string can be key!";
        }
    }
}

// Check if dictionary extensions aren't implemented yet.
// Removes a key value pair
if (!JSdict.prototype.remove) {
    JSdict.prototype.remove = function (key) {
        if (key == null) {
            return "Key cannot be null";
        }
        if (keysLength != valsLength) {
            return "Dictionary inconsistent. Keys length don't match values!";
        }
        var keysLength = this.Keys.length;
        var valsLength = this.Values.length;
        var flag = false;
        for (var i = 0; i < keysLength; i++) {
            if (this.Keys[i] == key) {
                this.Keys.shift(key);
                this.Values.shift(this.Values[i]);
                flag = true;
                break;
            }
        }
        if (!flag) {
            return "Key does not exist";
        }
    }
}

The above implementation can now be used to simulate a dictionary as:

var dict = new JSdict();

dict.add(1, "one")

dict.add(1, "one more")
"Duplicate keys not allowed!"

dict.getVal(1)
"one"

dict.update(1, "onne")

dict.getVal(1)
"onne"

dict.remove(1)

dict.getVal(1)
"Key not found!"

This is just a basic simulation. It can be further optimized by implementing a better running time algorithm to work in atleast O(nlogn) time complexity or even less. Like merge/quick sort on arrays and then some B-search for lookups. I Didn't give a try or searched about mapping a hash function in JS.

Also, Key and Value for the JSdict obj can be turned into private variables to be sneaky.

Hope this helps!

EDIT >> After implementing the above, I personally used the JS objects as associative arrays that are available out-of-the-box.

However, I would like to make a special mention about two methods that actually proved helpful to make it a convenient hashtable experience.

Viz: dict.hasOwnProperty(key) and delete dict[key]

Read this post as a good resource on this implementation/usage. Dynamically creating keys in JavaScript associative array

THanks!

Community
  • 1
  • 1
Vaibhav
  • 2,527
  • 1
  • 27
  • 31
7

Use JavaScript objects. You can access their properties like keys in a dictionary. This is the foundation of JSON. The syntax is similar to Python dictionaries. See: JSON.org

Adam
  • 43,763
  • 16
  • 104
  • 144
  • "Watch" out! Object prototype methods like "watch" can bite you this way. Even if you don't have any of those, you'll at least have "[constructor](https://stackoverflow.com/questions/47007275/javascript-reserved-word-and-object)". – krubo Feb 10 '21 at 20:15
4

An old question but I recently needed to do an AS3>JS port, and for the sake of speed I wrote a simple AS3-style Dictionary object for JS:

http://jsfiddle.net/MickMalone1983/VEpFf/2/

If you didn't know, the AS3 dictionary allows you to use any object as the key, as opposed to just strings. They come in very handy once you've found a use for them.

It's not as fast as a native object would be, but I've not found any significant problems with it in that respect.

API:

//Constructor
var dict = new Dict(overwrite:Boolean);

//If overwrite, allows over-writing of duplicate keys,
//otherwise, will not add duplicate keys to dictionary.

dict.put(key, value);//Add a pair
dict.get(key);//Get value from key
dict.remove(key);//Remove pair by key
dict.clearAll(value);//Remove all pairs with this value
dict.iterate(function(key, value){//Send all pairs as arguments to this function:
    console.log(key+' is key for '+value);
});


dict.get(key);//Get value from key
MickMalone1983
  • 1,054
  • 8
  • 17
  • 1
    Nice and useful library! I have added a get function, which I thought was missing and fixed some minor syntax issues (missing semicolon etc). Here's the modified fiddle: [Dictionary in JSFiddle](http://jsfiddle.net/evPhE/3/) – Matt Oct 07 '13 at 13:21
  • Good job mate, dunno why that wasn't in there! – MickMalone1983 May 12 '14 at 13:34
2

Firefox 13+ provides an experimental implementation of the map object similar to the dict object in python. Specifications here.

It's only avaible in firefox, but it looks better than using attributes of a new Object(). Citation from the documentation :

  • 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.
mquandalle
  • 2,600
  • 20
  • 24