Skip to content

Commit 47b7fe3

Browse files
committed
New: HashMap implementation
1 parent 9cc359c commit 47b7fe3

File tree

8 files changed

+909
-6
lines changed

8 files changed

+909
-6
lines changed

src/data-structures/doubly-linked-list/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ A JavaScript implementation of a doubly linked list. This class uses the convent
1111
1. There is a `[Symbol.iterator]` method so each instance is iterable.
1212
1. The `size` getter property instead of a `length` data property to indicate that the size of the list is dynamically counted rather than stored.
1313
1. Defining a `values()` generator method.
14-
1. Defining a `find()` method for searching the list.
14+
1. Defining a `find()` method for searching the list to return data.
15+
1. Defining a `findIndex()` method for searching the list to return an index.
1516
1. Returning `undefined` from `get()` when no such index exists.
1617

1718
Read the [blog post](https://humanwhocodes.com/blog/2019/02/computer-science-in-javascript-doubly-linked-lists/) about the design of this class.
@@ -47,6 +48,7 @@ let index = list.indexOf("foo");
4748

4849
// search for a value
4950
let result = list.find(value => value.length > 3);
51+
let foundIndex = list.findIndex(value => value.length > 3);
5052

5153
// convert to an array using iterators
5254
let array1 = [...list.values()];

src/data-structures/doubly-linked-list/doubly-linked-list.js

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,45 @@ class DoublyLinkedList {
408408
* of the loop below.
409409
*/
410410
let current = this[head];
411+
412+
/*
413+
* This loop checks each node in the list to see if it matches.
414+
* If a match is found, it returns the data immediately, exiting the
415+
* loop because there's no reason to keep searching. The search
416+
* continues until there are no more nodes to search (when `current` is `null`).
417+
*/
418+
while (current !== null) {
419+
if (matcher(current.data)) {
420+
return current.data;
421+
}
422+
423+
// traverse to the next node in the list
424+
current = current.next;
425+
}
426+
427+
/*
428+
* If execution gets to this point, it means we reached the end of the
429+
* list and didn't find `data`. Just return `undefined` as the
430+
* "not found" value.
431+
*/
432+
return undefined;
433+
}
434+
435+
/**
436+
* Returns the index of the first item that matches a given function.
437+
* @param {Function} matcher A function returning true when an item matches
438+
* and false when an item doesn't match.
439+
* @returns {int} The index of the first item that matches a given function
440+
* or -1 if there are no matching items.
441+
*/
442+
findIndex(matcher) {
443+
444+
/*
445+
* The `current` variable is used to iterate over the list nodes.
446+
* It starts out pointing to the head and is overwritten inside
447+
* of the loop below.
448+
*/
449+
let current = this[head];
411450

412451
/*
413452
* The `index` variable is used to track how deep into the list we've
@@ -418,13 +457,13 @@ class DoublyLinkedList {
418457

419458
/*
420459
* This loop checks each node in the list to see if it matches.
421-
* If a match is found, it returns the data immediately, exiting the
460+
* If a match is found, it returns the index immediately, exiting the
422461
* loop because there's no reason to keep searching. The search
423462
* continues until there are no more nodes to search (when `current` is `null`).
424463
*/
425464
while (current !== null) {
426465
if (matcher(current.data)) {
427-
return current.data;
466+
return index;
428467
}
429468

430469
// traverse to the next node in the list
@@ -436,10 +475,10 @@ class DoublyLinkedList {
436475

437476
/*
438477
* If execution gets to this point, it means we reached the end of the
439-
* list and didn't find `data`. Just return `undefined` as the
478+
* list and didn't find `data`. Just return -1 as the
440479
* "not found" value.
441480
*/
442-
return undefined;
481+
return -1;
443482
}
444483

445484
/**

src/data-structures/doubly-linked-list/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@humanwhocodes/doubly-linked-list",
3-
"version": "2.1.0",
3+
"version": "2.2.0",
44
"description": "A doubly linked list implementation in JavaScript",
55
"main": "doubly-linked-list.js",
66
"scripts": {
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# JavaScript Hash Map Class
2+
3+
by [Nicholas C. Zakas](https://humanwhocodes.com)
4+
5+
If you find this useful, please consider supporting my work with a [donation](https://humanwhocodes.com/donate).
6+
7+
## Overview
8+
9+
A JavaScript implementation of a hash map where all keys must be strings. This class uses the conventions of built-in JavaScript collection objects, such as:
10+
11+
1. There is a `[Symbol.iterator]` method so each instance is iterable.
12+
1. The `size` getter property instead of a `length` data property to indicate that the size of the list is dynamically counted rather than stored.
13+
1. Defining `entries()`, `keys()`, and `values()` generator methods.
14+
15+
## Usage
16+
17+
Use CommonJS to get access to the `HashMap` constructor:
18+
19+
```js
20+
const { HashMap } = require("@humanwhocodes/hash-map");
21+
```
22+
23+
Each instance of `HashMap` has the following properties and methods:
24+
25+
```js
26+
const map = new HashMap();
27+
28+
// add an item
29+
map.set("foo", 1);
30+
31+
// get the value of an item
32+
let value = map.get("foo");
33+
34+
// get the number of items
35+
let count = map.size;
36+
37+
// does the key exist in the map?
38+
let found = map.has("foo");
39+
40+
// remove a key
41+
map.delete("foo");
42+
43+
// get all key-value pairs
44+
let entries1 = [...map.entries()];
45+
let entries2 = [...map];
46+
47+
// get all keys
48+
let keys = [...map.keys()];
49+
50+
// get all values
51+
let values = [...map.values()];
52+
53+
// remove all items
54+
map.clear();
55+
```
56+
57+
## Note on Code Style
58+
59+
You may find the code style of this module to be overly verbose with a lot of comments. That is intentional, as the primary use of this module is intended to be for educational purposes. There are frequently more concise ways of implementing the details of this class, but the more concise ways are difficult for newcomers who are unfamiliar with linked lists as a concept or JavaScript as a whole.
60+
61+
## Note on Usage
62+
63+
This module is intended for educational purposes. For production purposes, you should use the native JavaScript `Map` class.
64+
65+
## Issues and Pull Requests
66+
67+
As this is part of series of tutorials I'm writing, only bug fixes will be accepted. No new functionality will be added to this module.
68+
69+
## License
70+
71+
MIT

0 commit comments

Comments
 (0)