Skip to content

Commit 9cc359c

Browse files
committed
Update: Add find() method to DoublyLinkedList
1 parent ad425c0 commit 9cc359c

File tree

4 files changed

+79
-1
lines changed

4 files changed

+79
-1
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ 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.
1415
1. Returning `undefined` from `get()` when no such index exists.
1516

1617
Read the [blog post](https://humanwhocodes.com/blog/2019/02/computer-science-in-javascript-doubly-linked-lists/) about the design of this class.
@@ -44,6 +45,9 @@ let count = list.size;
4445
// get the index of a value
4546
let index = list.indexOf("foo");
4647

48+
// search for a value
49+
let result = list.find(value => value.length > 3);
50+
4751
// convert to an array using iterators
4852
let array1 = [...list.values()];
4953
let array2 = [...list];

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,55 @@ class DoublyLinkedList {
392392
*/
393393
return -1;
394394
}
395+
396+
/**
397+
* Returns the first item that matches a given function.
398+
* @param {Function} matcher A function returning true when an item matches
399+
* and false when an item doesn't match.
400+
* @returns {*} The first item that returns true from the matcher, undefined
401+
* if no items match.
402+
*/
403+
find(matcher) {
404+
405+
/*
406+
* The `current` variable is used to iterate over the list nodes.
407+
* It starts out pointing to the head and is overwritten inside
408+
* of the loop below.
409+
*/
410+
let current = this[head];
411+
412+
/*
413+
* The `index` variable is used to track how deep into the list we've
414+
* gone. This is important because this is the value that is returned
415+
* from this method.
416+
*/
417+
let index = 0;
418+
419+
/*
420+
* 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
422+
* loop because there's no reason to keep searching. The search
423+
* continues until there are no more nodes to search (when `current` is `null`).
424+
*/
425+
while (current !== null) {
426+
if (matcher(current.data)) {
427+
return current.data;
428+
}
429+
430+
// traverse to the next node in the list
431+
current = current.next;
432+
433+
// keep track of where we are
434+
index++;
435+
}
436+
437+
/*
438+
* 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
440+
* "not found" value.
441+
*/
442+
return undefined;
443+
}
395444

396445
/**
397446
* Removes the node from the given location in the list.

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.0.1",
3+
"version": "2.1.0",
44
"description": "A doubly linked list implementation in JavaScript",
55
"main": "doubly-linked-list.js",
66
"scripts": {

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,31 @@ describe("DoublyLinkedList", () => {
336336

337337
});
338338

339+
describe("find()", () => {
340+
341+
it("should return undefined when the list is empty", () => {
342+
assert.isUndefined(list.find(() => true));
343+
});
344+
345+
it("should return 1 when the matching value is found", () => {
346+
list.add(1);
347+
assert.strictEqual(list.find(value => (value > 0)), 1);
348+
});
349+
350+
it("should return 2 when the matching value is second", () => {
351+
list.add(1);
352+
list.add(2);
353+
assert.strictEqual(list.find(value => (value > 1)), 2);
354+
});
355+
356+
it("should return undefined when the list doesn't contain a match", () => {
357+
list.add(1);
358+
list.add(2);
359+
assert.isUndefined(list.find((value) => value > 2));
360+
});
361+
362+
});
363+
339364
["values", Symbol.iterator].forEach(method => {
340365

341366
describe(String(method) + "()", () => {

0 commit comments

Comments
 (0)