npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@toolbuilder/list

v1.2.4

Published

Tiny, mutable, double linked, iterable list.

Downloads

186

Readme

List

Small, mutable, double linked, iterable list.

List supports iteration over values and nodes. If you wish to have functions like map, filter, forEach, and such, please use an iterable or Observable library. One such possibility is Iterablefu.

Installation

npm install --save @toolbuilder/list

Getting Started

Import the library like this. Typescript users may also want to import Node for explicit typing.

import { List } from '@toolbuilder/list'

Quick example:

import { List } from '@toolbuilder/list'

const list = new List(['A', 'B', 'D'])
console.log(list.length) // prints 3
list.push('E') // add 'E' to the end of the list
console.log(list.first()) // prints 'A'
const node = list.find(value => value === 'B')
list.insertAfter(node, 'C') // list is ['A', 'B', 'C', 'D', 'E'] now
console.log(list.last()) // prints 'B'
for (const value of list) {
  // do something here
}

There are four ways to construct a list:

import { List } from '@toolbuilder/list'

const list1 = new List(['A', 'B', 'C']) // parameter optional
const list2 = List.from(['A', 'B', 'C']) // parameter optional
const list3 = List.of('A', 'B', 'C') // parameters optional
const list4 = list1.slice() // optional parameters will produce subset

There are three methods for iterating over the contents of a list:

// reverse a list
const list = new List(['a', 'b'])
const reversed = List.from(list.nodesReversed())

Some methods work with Node objects to change the structure of the list. For convenience, other methods work with list values directly. For example, List.first() returns the value of the first element, and List.firstNode() returns the first Node. Nodes are required for operations such as List.insertBefore(node, value) and List.remove(node).

These methods use values, not Nodes:

API

API documentation follows.

The JsDoc comments use Typescript types so the Typescript compiler can generate a types file. Some key points:

  • The List class is generic, so the type of the value is Type. So a list containing strings would be List<string>
  • Objects that implement the iterable protocol are represented by Iterable. So an iterable that provides strings would be Iterable<string>.
  • Generator objects are represented by IterableIterator. The Generator object is returned by a generator function and conforms to both the iterable protocol and the iterator protocol.

Node

The Node object is used by insertBefore and insertAfter to specify where to insert a new value. Other methods return Nodes to support using those two methods. Nodes are only valid for the List that created them.

The Node object has a value property, which provides the value associated with that node. Other properties and methods of the Node object are subject to change, and are not considered part of the public API.

Parameters:

  • prev Node<Type>
  • next Node<Type>
  • value Type only this property is part of the public API
const list = List.of('A', 'C')
list.insertAfter(list.firstNode(), 'B')
console.log([...list]) // prints ['A', 'B', 'C']
const node = list.firstNode()
console.log(node.value) // prints 'A'

List

Double-linked list.

Parameters:

  • iterable Iterable<Type>? builds list using iterable (optional, default null)

length

Provides the number of elements in the list.

Type: number

first

Provides the first value in the list. Returns undefined if the list is empty.

const list = List.from(['a', 'b', 'c'])
console.log(list.first()) // prints 'a'

Returns Type first value in list

last

Provides the last value in the list. Returns undefined if the list is empty.

const list = List.from(['A', 'B', 'C'])
console.log(list.last()) // prints 'C'

Returns Type last value in the list

firstNode

Provides the first node in the list. Returns undefined if list is empty.

const list = List.from(['a', 'b', 'c'])
const node = list.firstNode()
console.log(node.value) // prints 'a'

Returns Node<Type> first node in list

lastNode

Provides the last node in the list. Returns undefined if list is empty.

const list = List.from(['A', 'B', 'C'])
const node = list.lastNode()
console.log(node.value) // prints 'C'

Returns Node<Type> last node in list

previousNode

Provides the node that comes before the provided node.

Parameters:

  • node Node<Type> any Node element provided by the List instance
const list = List.from(['A', 'B', 'C'])
const node = list.lastNode()
const prevNode = list.previousNode(node)
console.log(prevNode.value) // prints 'B'

Returns Node<Type> value - the Node that comes before provided node or undefined if provided node is the first node or undefined.

nextNode

Provides the node that comes after the provided node.

Parameters:

  • node Node<Type> any Node element provided by the List instance
const list = List.from(['A', 'B', 'C'])
const node = list.firstNode()
const nextNode = list.nextNode(node)
console.log(nextNode.value) // prints 'B'

Returns Node<Type> value - the Node that follows provided node or undefined if provided node is the last node or undefined.

insertAfter

Insert value after a node.

Parameters:

  • prevNode Node<Type> node from this list to insert value behind
  • value Type value to insert
const list = new List(['A', 'B', 'D'])
const prevNode = list.find(value => value === 'B')
list.insertAfter(prevNode, 'C')
console.log([...list]) // prints ['A', 'B', 'C', 'D']

Returns Node<Type> the newly created node

insertBefore

Insert value before a node.

Parameters:

  • nextNode Node<Type> node from this list to insert value in front of
  • value Type value to insert
const list = new List(['A', 'C', 'D'])
const nextNode = list.find(value => value === 'C')
list.insertBefore(nextNode, 'B')
console.log([...list]) // prints ['A', 'B', 'C', 'D']

Returns Node<Type> the newly created node

remove

Remove a node from the list.

Parameters:

  • node Node<Type> the node to remove from the list. The node is no longer useable after this call, and no longer references the associated value.
const list = new List(['A', 'B', 'C', 'D'])
const node = list.find(value => value === 'C')
list.remove(node)
// at this point the variable 'node' is no longer useable, node.value will return null.
console.log([...list]) // prints ['A', 'B', 'D']

push

Add a value to the end of the list.

Parameters:

  • value Type to be added to end of list
const list = new List(['A', 'B', 'C'])
const node = list.push('D')
console.log([...list]) // prints ['A', 'B', 'C', 'D']
console.log(node.value) // prints 'D'

Returns Node<Type> the newly created Node

pop

Remove the last value in the list.

const list = new List(['A', 'B', 'C'])
const value = list.pop()
console.log([...list]) // prints ['A', 'B']
console.log(value) // prints 'C'

Returns Type the value of the removed node, or undefined if the list was empty

find

Find the first value in the list where callback(value) returns truthy.

Parameters:

  • callback FindFunction<Type> called for each value in the list until returns truthy
  • thisArg object? value to use as this when calling callback, defaults to null (optional, default null)
const list = new List(['A', 'B', 'C', 'D'])
const node = list.find(value => value === 'C')
console.log(node.value) // prints 'C'

Returns Node<Type> the node that contains the value. The value property will provide the value. Returns undefined if there was no value where callback returned truthy.

shift

Remove first node from list, and return the value. When combined with push, this enables List to work like a FIFO queue.

const list = List.from(['A', 'B', 'C'])
const value = list.shift()
console.log(value) // prints 'A'
console.log([...list]) // prints ['B', 'C']

Returns Type the value of the first node before the call to shift, or undefined if the list is empty.

unshift

Push a value onto the front of the list.

Parameters:

  • value Type to be added to front of list
const list = new List(['B', 'C', 'D'])
const node = list.unshift('A')
console.log([...list]) // prints ['A', 'B', 'C', 'D']
console.log(node.value) // prints 'A'

Returns Node<Type> the newly created Node

slice

Creates a shallow copy of the list, with optional parameters to create a subset of the original list. The Nodes of the copy are different, and cannot be used with the original list. Modifying the list will not modify the parent list. However, modifying values will modify values in the parent list if they are not primitives.

Parameters:

  • firstNode Node<Type>? copy starts with this node. If firstNode is undefined, the first value of the copy is list.first(). (optional, default undefined)
  • lastNode Node<Type>? last value of copy is list.previousNode(lastNode).value. If lastNode is undefined, the last value of the copy is list.last() (optional, default undefined)
const list = List.of('A', 'B', 'C', 'D', 'E')
const cNode = list.find(c => c === 'C')
console.log([...list.slice()]) // prints ['A', 'B', 'C', 'D', 'E']
console.log([...list.slice(cNode)]) // prints ['C', 'D', 'E']
console.log([...list.slice(list.firstNode(), cNode)]) // prints ['A', 'B']
console.log([...list.slice(cNode, cNode)]) // prints []

Returns List<Type> a shallow copy of the list with the specified values

nodes

Generator function that produces each node of the list in order from first to last. The value property of each node provides the associated value.

Unexpected results may happen if the list structure is modified during iteration.

Parameters:

  • first Node<Type>? iteration starts with this node. If first is undefined, the first node returned is list.firstNode(). (optional, default undefined)
  • last Node<Type>? last node returned is list.previousNode(last). If last is undefined, the last node returned is list.lastNode() (optional, default undefined)
const list = List.from([1, 2, 3, 4])
const array = []
for (const node of list.nodes()) {
  array.push(node.value)
}
console.log(array) // prints [1, 2, 3, 4]

Returns IterableIterator<Node<Type>>

nodesReversed

Generator function that produces each node in order from last to first.

Unexpected results may happen if the list structure is modified during iteration.

Returns IterableIterator<Node<Type>>

from

Static constructor.

Parameters:

  • iterable Iterable<U>? build list from iterable, may be null (optional, default null)
const list = List.from(['A', 'B'])
console.log([...list]) // prints ['A', 'B']

Returns List<U>

of

Static constructor from parameter values.

Parameters:

  • values ...V each value becomes an element of the list in the order provided
const list = List.of(1, 2, 'B')
console.log([...list]) // prints [1, 2, 'B']

Returns List<V>

FindFunction

Callback function for find. Returns truthy when value is found.

Type: Function

Parameters:

  • value T candidate list value
const list = List.from(['a', 'b'])
const findFunction = (value) => value === 'b'
const node = list.find(findFunction)
console.log(node.value) // prints 'b'

Returns any truthy if value is what you're looking for

Symbol.iterator

Iterable protocol over the values in the list.

Parameters:

  • firstNode Node<Type>? iteration starts with this node. If firstNode is undefined, the first value returned is list.first().
  • lastNode Node<Type>? last value returned is list.previousNode(lastNode).value. If lastNode is undefined, the last value returned is list.last()
const list = List.from([1, 2, 3, 4])
const array = []
for (const value of list) {
  array.push(value)
}
console.log(array) // prints [1, 2, 3, 4]

Returns IterableIterator<Type>

Releases

See the change log

Contributing

Contributions are welcome. Please create a pull request.

  • I use pnpm instead of npm.
  • Pack file verification requires pnpm to be installed globally.
    • npm install -g pnpm
    • pnpm install to get the dependencies
    • pnpm test to run unit tests
    • pnpm run check:packfile generates pack file to run unit tests against Node ES and CommonJS projects, as well as Electron.
    • pnpm run check validates the package is ready for commit

Issues

This project uses Github issues.

License

MIT