npm package: @psenger/linked-list
Description: Linked List for NodeJS
Author: Philip A Senger
Latest version: 1.0.5

# Linked List

_ES6 Linked List for NodeJS_

> A Linked List, is a collection of elements whose order / sequence is not determined by physical
> placement in memory, but rather by each element which points to either the next or previous
> element.

[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com)

<!--START_SECTION:toc-->

## Table of contents
- [Linked List](#linked-list)
  * [Installation Instructions](#installation-instructions)
  * [API](#api)
    + [LinkedList](#linkedlist)
      - [Parameters](#parameters)
      - [clear](#clear)
      - [length](#length)
      - [setHead](#sethead)
        * [Parameters](#parameters-1)
      - [getHead](#gethead)
      - [setTail](#settail)
        * [Parameters](#parameters-2)
      - [getTail](#gettail)
      - [prepend](#prepend)
        * [Parameters](#parameters-3)
        * [Examples](#examples)
      - [prependAll](#prependall)
        * [Parameters](#parameters-4)
      - [append](#append)
        * [Parameters](#parameters-5)
        * [Examples](#examples-1)
      - [appendAll](#appendall)
        * [Parameters](#parameters-6)
        * [Examples](#examples-2)
      - [forward](#forward)
        * [Examples](#examples-3)
      - [reverse](#reverse)
        * [Examples](#examples-4)
      - [find](#find)
        * [Parameters](#parameters-7)
        * [Examples](#examples-5)
    + [LinkedList~LinkedListPredicate](#linkedlistlinkedlistpredicate)
      - [Parameters](#parameters-8)
    + [LinkedList~SurroundingNodes](#linkedlistsurroundingnodes)
      - [Properties](#properties)
    + [Node~NodeOption](#nodenodeoption)
      - [Properties](#properties-1)
    + [Node](#node)
      - [Parameters](#parameters-9)
      - [getData](#getdata)
      - [setData](#setdata)
        * [Parameters](#parameters-10)
      - [getNext](#getnext)
      - [setNext](#setnext)
        * [Parameters](#parameters-11)
      - [getPrev](#getprev)
      - [setPrev](#setprev)
        * [Parameters](#parameters-12)
  * [Example Usage](#example-usage)
  * [Deployment Steps](#deployment-steps)
  * [License](#license)

<!--END_SECTION:toc-->

<!--START_SECTION:file:INSTALLATION.md-->
## Installation Instructions

```bash
npm install @psenger/linked-list --save
```

or

```bash
yarn add @psenger/linked-list
```

<!--END_SECTION:file:INSTALLATION.md-->

<!--START_SECTION:jsdoc-->
## API

<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

### LinkedList

Linked List - Constructed with either a Data Object ( which will be wrapped with a Node ) or a
Node with data in it already. Alternatively, you can construct the Linked List with no
parameters.

#### Parameters

*   `data` **([Node][1] | [Object][2] | [undefined][3] | null)** Node, an Object as the data, undefined or null. (optional, default `null`)

#### clear

Clear all out the values. Resetting the Linked List.

#### length

Determine the length of the linked List. The Linked List can be altered by means outside
the control of the LinkedList Object, thereby bypassing the any functions on this object.
Therefore, the length is calculated by iterating over every value in the list. Which can be
expensive to execute if the list is large.

Returns **[number][4]** the length

#### setHead

Set the head, to either a new value, which will be encapsulated as a new Node, or by passing a
Node. Either way, the Node's next and previous values will be modified and the value or
node that is passed becomes the new head. Consequently, passing either null or undefined,
will result in clearing the entire linked list.

##### Parameters

*   `newHead` **([Object][2] | [Node][1] | null | [undefined][3])** the new head, supporting either a Node, or data.

#### getHead

Get the Head of this Linked List.

Returns **(null | [Node][1])** The head, or null.

#### setTail

Set the tail, to either a new value, which will be encapsulated as a new Node, or a pass a
Node. Either way, the Node's next and previous values will be modified and the value or
node that is passed becomes the new tail. Consequently, passing either null or undefined,
will result in clearing the entire linked list.

##### Parameters

*   `newTail` **([Object][2] | [Node][1] | null | [undefined][3])** the new tail, supporting either a Node, or data.

#### getTail

get the Tail of this Linked List

Returns **(null | [Node][1])** The tail, or null.

#### prepend

Prepend a new Node or Data to the head. Warning, passing null will clear the Linked List.

##### Parameters

*   `data` **([Object][2] | [Node][1] | null | [undefined][3])** passing either a Node or data, null will reset
    the Linked List.

##### Examples

```javascript
const ll = new LinkedList();
const nn = new Node();
nn.setData('C')
ll.prepend('A').prepend(new Node({data:'B'})).prepend(nn)
for ( let node of ll.forward ) {
  console.log(node.getData());
}
console.log( 'length =', ll.getSize() );
ll.append( null )
console.log( 'length =', ll.getSize() );
> C
> B
> A
> length = 3
> length = 0
```

Returns **[LinkedList][5]** A reference to this object allowing chaining.

#### prependAll

Prepend all the values from left to right of the iterator passed in.

##### Parameters

*   `values` **Iterable** Iterable values to prepend to the tail, can be either data or a Node

Returns **[LinkedList][5]** A reference to this object allowing chaining.

#### append

Append a new Node or Data to the tail. Warning, passing null will clear the Linked List.

##### Parameters

*   `data` **([Object][2] | [Node][1] | null | [undefined][3])** passing either a Node or data, null will reset the Linked List.

##### Examples

```javascript
const ll = new LinkedList();
const nn = new Node();
nn.setData('C')
ll.append('A').append(new Node({data:'B'})).append(nn)
for ( let node of ll.forward ) {
   console.log(node.getData());
}
console.log( 'length =', ll.getSize() );
ll.append( null )
console.log( 'length =', ll.getSize() );
> A
> B
> C
> length = 3
> length = 0
```

Returns **[LinkedList][5]** A reference to this object allowing chaining.

#### appendAll

Append all the values from left to right of the iterator passed in.

##### Parameters

*   `values` **Iterable** Iterable values to append to the beginning, can be either data or a Node

##### Examples

```javascript
const ll = new LinkedList();
const nn = new Node();
nn.setData('C')
ll
.appendAll([
  'A',
  new Node({data: 'B'})
])
.appendAll([
  nn
])
for (let node of ll.forward) {
  console.log(' > ', node.getData());
}
> A
> B
> C
```

Returns **[LinkedList][5]** A reference to this object allowing chaining.

#### forward

A Forward iterator through the Linked List

##### Examples

```javascript
let ll = new LinkedList();
ll.appendAll(['A','B','E','F'])
for ( let node of ll.reverse ) {
   console.log(node.getData());
}
> F
> E
> B
> A
ll.clear();
ll.appendAll([1,2,3,4])
const y = Array.from( ll.forward, node => node.getData() ).filter( v => v % 2 === 0 )
console.log(y);
> [ 2, 4 ]
```

#### reverse

A Reverse iterator through the Linked List

##### Examples

```javascript
const ll = new LinkedList();
ll.appendAll(['A','B','E','F'])
for ( let node of ll.reverse ) {
   console.log(node.getData());
}
> F
> E
> B
> A
ll.clear();
ll.appendAll([1,2,3,4])
const y = Array.from( ll.reverse, node => node.getData() ).filter( v => v % 2 === 0 )
console.log(y);
> [ 4, 2 ]
```

#### find

Find provides a call back that can be used to select nodes from the Linked List.

##### Parameters

*   `predicate` **[LinkedList~LinkedListPredicate][6]** 
*   `options` **[Object][2]**  (optional, default `{iterator:this.forward,once:true}`)

    *   `options.iterator` **Iterator** The iterator to use, defaults to forward. (optional, default `this.forward`)
    *   `options.once` **[Boolean][7]** Indicates if the iteration is to halt if found once. (optional, default `true`)

##### Examples

```javascript
const ll = new LinkedList();
const evenCallBack = (cn,pn,nn,iteration,hitCount,linkedList) => cn.getData() % 2 === 0;
ll.appendAll([1,2,3,4])
const results = ll.find(evenCallBack,{once:false}).map(({currentNode})=>currentNode?.getData());
console.log('Even values=', results);
// Even values= [ 2, 4 ]
ll.clear();
const findIt = (value) => (cn,pn,nn,iteration,hitCount,linkedList) => cn.getData() === value;
ll.appendAll(['A','B', 'C','D']) // insert Z between B and C
const [ { previousNode, currentNode, nextNode } ] = ll.find(findIt('B'),{once:true});
console.log('previousNode', previousNode?.getData());
// previousNode A
console.log('currentNode', currentNode?.getData());
// currentNode B
console.log('nextNode', nextNode?.getData());
// nextNode C
const newNode = new Node();
newNode.setData('Z');
currentNode?.setNext( newNode );
nextNode?.setPrev( newNode );
newNode.setPrev( currentNode );
newNode.setNext( nextNode );
console.log('---- Forward ----');
for ( let node of ll.forward ) {
   console.log(node.getData());
}
// ---- Forward ----
// A
// B
// Z
// C
// D
console.log('---- Reverse ----');
for ( let node of ll.reverse ) {
   console.log(node.getData());
}
// ---- Reverse ----
// D
// C
// Z
// B
// A
```

Returns **[Array][8]<[LinkedList~SurroundingNodes][9]>** matching nodes

### LinkedList~LinkedListPredicate

Callback, used by find to predicate nodes, in the Linked List.

Type: [Function][10]

#### Parameters

*   `currentNode` **(null | [Node][1])** The current Node
*   `previousNode` **(null | [Node][1])** The previous Node
*   `nextNode` **(null | [Node][1])** The next Node
*   `iteration` **[number][4]** Iteration number
*   `hitCount` **[number][4]** A running count of all the evaluated predicates that matched true.
*   `scope` **[LinkedList][5]** The LinkedList Object.

Returns **[boolean][7]** true indicates a match and will collect matching node(s)

### LinkedList~SurroundingNodes

Type: [Object][2]

#### Properties

*   `previousNode` **(null | [Node][1])** previous node
*   `currentNode` **(null | [Node][1])** current node
*   `nextNode` **(null | [Node][1])** next node

### Node~NodeOption

A Node constructor option object

Type: [Object][2]

#### Properties

*   `data` **([Object][2] | null)** Any kind of data you want to store.
*   `next` **([Node][1] | null)** Next node
*   `prev` **([Node][1] | null)** Previous node

### Node

Node, the internal class used within the linked list to assist in linking elements.

#### Parameters

*   `props` **[Node~NodeOption][11]** the Options to pass to the
    constructor (optional, default `{data:null,next:null,prev:null}`)

    *   `props.data` **([Object][2] | null)** the data to store (optional, default `null`)
    *   `props.next` **([Node][1] | null)** the next node, or null (optional, default `null`)
    *   `props.prev` **([Node][1] | null)** the previous node, or null (optional, default `null`)

#### getData

Get the data from this node, which can be what ever you want.

Returns **(any | null)** the data stored here.

#### setData

Set the data in this node.

##### Parameters

*   `data` **(any | null)** the data to store.

#### getNext

Get the next node, null indicates that it is the end.

Returns **([Node][1] | null)** the next node.

#### setNext

Set the next node, null indicates the end.

##### Parameters

*   `node` **([Node][1] | null)** the next node.

#### getPrev

Get the previous node. The value null indicate the end has been reached.

Returns **([Node][1] | null)** the previous node.

#### setPrev

Set the previous node, null indicates the end.

##### Parameters

*   `node` **([Node][1] | null)** the previous node.

[1]: #node

[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object

[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined

[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number

[5]: #linkedlist

[6]: #linkedlistlinkedlistpredicate

[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean

[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array

[9]: #linkedlistsurroundingnodes

[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function

[11]: #nodenodeoption

<!--END_SECTION:jsdoc-->

<!--START_SECTION:file:TUTORIAL.md-->
## Example Usage

```javascript
const LinkedList = require('./LinkedList');

const ll = new LinkedList();
ll.append('A').append('B').append('C')
for (let node of ll.forward) {
  console.log(node.getData());
}
console.log('head=',ll.getHead().getData());
console.log('tail=',ll.getTail().getData());
```

<!--END_SECTION:file:TUTORIAL.md-->

## Deployment Steps

These are notes for deploying to NPM. I used `npmrc` to manage my NPM identities
(`npm i npmrc -g` to install ). Then I created a new profile called `public` with
(`npmrc -c public`) and then switch to it with `npmrc public`.

* create a pull request from `dev` to `main`
* check out `main`
* `npm version patch -m "message here" or minor`
* `npm publish --access public`
* Then switch to `dev` branch
* And then merge `main` into `dev` and push `dev` to origin

## License

<!--START_SECTION:file:LICENSE-->
MIT License

Copyright (c) 2021 Philip A Senger

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

<!--END_SECTION:file:LICENSE-->

MIT © [psenger](https://github.com/psenger)