DEV Community

Cover image for Creating the Dictionary Class with JavaScript
Christina
Christina

Posted on

JavaScript Dictionary Creating the Dictionary Class with JavaScript

To continue my exploration of data structures, I wanted to write this article on creating our own dictionary class in JavaScript.

A dictionary, also known as a map, is used to store [key, value] pairs, where the key can be used to look up a particular element. Dictionaries are often used to store the reference address of objects or for a project like an actual dictionary or an address book, for example.

Creating the Dictionary class

The base structure of our Dictionary class will look like this:

import { defaultToString } from '../util';

export default class Dictionary {
    constructor(toStrFn = defaultToString) { // defaultToString below
        this.toStrFn = toStrFn;
        this.table = {};
    }
}
Enter fullscreen mode Exit fullscreen mode

As you can see, we are storing the elements of the Dictionary class in an Object instance and the [key, value] pairs are being stored as table[key] = {key, value}.

Ideally, we would be storing keys of type string and any type of value but because JavaScript is not strongly typed, we cannot guarantee the key will be a string. Thus, we will have to transform whatever object is passed as the key into a string to make it easier to search and retrieve values. For this reason, we are passing in a function which will look something like this:

export function defaultToString(item) {
    if (item === null) {
        return 'NULL';
    } else if (item === undefined) {
        return 'UNDEFINED';
    } else if (typeof item === 'string' || item instanceof String) {
        return `${item}`;
    }
    return item.toString();
}
Enter fullscreen mode Exit fullscreen mode

Over the course of this article, we will cover the following methods for our dictionary:

  • hasKey(key): return true if the key exists in the dictionary.
  • set(key, value): add a new element to the dictionary. If the key already exists, the existing value will be overwritten with the new one.
  • remove(key): remove the value from the dictionary.
  • get(key): return the value associated with the passed key.
  • keys(): return an array of all the keys the dictionary contains.
  • values(): return an array of all the values of the dictionary.
  • keyValues(): return an array of all [key, value] pairs of the dictionary.
  • size(): return the number of values the dictionary contains.
  • isEmpty(): return true if the size equals zero.
  • clear(): remove all values from the dictionary.
  • forEach(callBackFn): iterate every value pair in the dictionary and perform the call back function.

Verify a key exists in the dictionary

The first method we will cover is the hasKey(key) method since we will need it for other methods.

hasKey(key) {
    return this.table[this.toStrFn(key)] != null;
}
Enter fullscreen mode Exit fullscreen mode

Set a key and value in the dictionary

Next up, the set(key, value) method which can be used to add a new value or update an existing one:

set(key, value) {
    if (key != null && value != null) {
        const tableKey = this.toStrFn(key);
        this.table[tableKey] = new ValuePair(key, value);
        return true;
    }
    return false;
}
Enter fullscreen mode Exit fullscreen mode

As you can see, we instantiated the class ValuePair which we define as follows:

class ValuePair(key, value) {
    constructor(key, value)  {
        this.key = key;
        this.value = value;
    }

    toString() {
        return `[${this.key}: ${this.value}]`;
    }
}
Enter fullscreen mode Exit fullscreen mode

Remove a value from the dictionary

The remove method is pretty straight forward at this point, especially with the help of the JavaScript delete operator:

remove(key) {
    if (this.hasKey(key)) {
        delete this.table[this.toStrFn((key))];
        return true;
    }
    return false;
}
Enter fullscreen mode Exit fullscreen mode

Retrieve a value from the dictionary

Next, we will write the get method in order to search for a particular key and retrieve its value:

get(key) {
    const valuePair = this.table[this.toStrFn(key)];
    return valuePair == null ? undefined : valuePair.value;
}
Enter fullscreen mode Exit fullscreen mode

keyValues, keys, and values methods

Now we will create some more supplementary but nevertheless useful methods. The valuePairs method will return an array with all ValuePair objects in the dictionary, using the built-in values method from the JavaScript Object class:

keyValues() {
    return Object.values(this.table);
}
Enter fullscreen mode Exit fullscreen mode

Next, we will write the keys method which returns all the original keys used to identify a value in the Dictionary class:

keys() {
    return this.keyValues().map(valuePair => valuePair.key);
}
Enter fullscreen mode Exit fullscreen mode

The values method will look similar to the keys method, returning an array of all values stored in the dictionary:

values() {
    return this.keyValues().map(valuePair => valuePair.value);
}
Enter fullscreen mode Exit fullscreen mode

Iterating each ValuePair of the dictionary

Let's write a forEach method that will iterate each ValuePair in the dictionary and evoke a callback function for each iteration:

forEach(callbackFn) {
    const valuePairs = this.keyValues();
    for (let i = 0; i < valuePairs.length; i++) {
        const result = callbackFn(valuePairs[i].key, valuePairs[i].value);
        if (result === false) {
            break;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

size, isEmpty, clear, and toString methods

size() {
    return this.keyValues().length;
}
Enter fullscreen mode Exit fullscreen mode

Note we could have evoked the Object.keys method instead (return Object.keys(this.table).length).

Now we can use our size method for isEmpty:

isEmpty() {
    return this.size() === 0;
}
Enter fullscreen mode Exit fullscreen mode

As expected, clear is very simple:

clear() {
    this.table = {};
}
Enter fullscreen mode Exit fullscreen mode

Finally, the toString method:

toString() {
    if (this.isEmpty()) {
        return '';
    }
    const valuePairs = this.keyValues();
    let objString = `${valuePairs[0].toString()}`;
    for (let i = 1; i < valuePairs.length; i++) {
        objString = `${objString}, ${valuePairs[i].toString()}`;
    }
    return objString;
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

I hope this article helped you gain a better understanding of dictionaries and the common methods associated with it. I sort of considered this to be a warm up for a later article I plan to write soon on Hash Tables so stay tuned for more!

Top comments (0)