reverse-iterable-map
Advanced tools
Comparing version 1.0.0 to 1.0.1
{ | ||
"name": "reverse-iterable-map", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "A reverse-iterable map implementation based on the built-in Map object", | ||
@@ -12,3 +12,3 @@ "main": "./src/reverse-iterable-map", | ||
"test": "npm run build && node --experimental-modules test/tests.mjs", | ||
"example": "npm run build && npx http-static" | ||
"examples": "npm run build && npx http-static" | ||
}, | ||
@@ -19,3 +19,8 @@ "repository": { | ||
}, | ||
"keywords": ["map", "linked-map", "reverse-iterable", "iterable-iterator"], | ||
"keywords": [ | ||
"map", | ||
"linked-map", | ||
"reverse-iterable", | ||
"iterable-iterator" | ||
], | ||
"author": { | ||
@@ -22,0 +27,0 @@ "name": "Philipp Rudloff", |
504
README.md
@@ -10,4 +10,4 @@ # reverse-iterable-map.js | ||
* [Tests](#tests) | ||
* [Why?](#why) | ||
* [But why a map?](#but-why-a-map) | ||
* [Documentation](#documentation) | ||
* [Why this was implemented](#why-this-was-implemented) | ||
@@ -20,3 +20,3 @@ ## Install | ||
``` | ||
```shell | ||
curl -O https://github.com/kleinfreund/reverse-iterable-map.js/blob/master/src/reverse-iterable-map.js | ||
@@ -35,3 +35,3 @@ ``` | ||
``` | ||
```shell | ||
npm install --save reverse-iterable-map | ||
@@ -58,5 +58,5 @@ ``` | ||
```shell | ||
npm run examples | ||
``` | ||
npm run example | ||
``` | ||
@@ -69,8 +69,494 @@ Prints test results to the console. | ||
``` | ||
```shell | ||
npm test | ||
``` | ||
## Why? | ||
## Documentation | ||
**Disclaimer**: The documentation section copies a lot of content from the [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) documentation on the Mozilla Developer Network. | ||
A `ReverseIterableMap` object iterates its elements in insertion or reverse-insertion order — a [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop returns an array of `[key, value]` for each iteration. | ||
### Constructor | ||
#### Syntax | ||
``` | ||
new ReverseIterableMap([iterable]) | ||
``` | ||
**Parameters**: | ||
* `iterable`: An [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol) oject whose elements are key-value pairs. | ||
In order to construct a `ReverseIterableMap` object from an array, it can be passed by calling the [`Array.prototype.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries) method. | ||
```js | ||
const map = new ReverseIterableMap([1, 2, 3].entries()); | ||
``` | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap(); | ||
``` | ||
```js | ||
const builtInArray = [1, 2, 3]; | ||
const map = new ReverseIterableMap(builtInArray.entries()); | ||
``` | ||
```js | ||
const builtInArrayOfArrays = [[0, 1], [1, 2], [2, 3]]; | ||
const map = new ReverseIterableMap(builtInArrayOfArrays); | ||
``` | ||
```js | ||
const builtInMap = new Map([['key1', 1], ['key2', 2], ['key3', 3]]); | ||
const map = new ReverseIterableMap(builtInMap); | ||
``` | ||
### `clear()` | ||
#### Syntax | ||
``` | ||
map.clear(); | ||
``` | ||
**Return value**: | ||
[`undefined`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined). | ||
#### Usage | ||
```js | ||
// Clears the underlying Map object | ||
// Sets the first and last node references to null | ||
map.clear(); | ||
``` | ||
### `has()` | ||
#### Syntax | ||
``` | ||
map.has(key); | ||
``` | ||
**Parameters**: | ||
* **key**: Required. The key of the element to test for presence in the `ReverseIterableMap` object. | ||
**Return value**: | ||
* **Boolean**: Returns `true` if an element with the specified key exists in the `ReverseIterableMap` object; otherwise `false`. | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap(['hey', 'beauty']); | ||
map.has(0); | ||
//> true | ||
map.has(1); | ||
//> true | ||
map.has(2); | ||
//> false | ||
``` | ||
### `get()` | ||
#### Syntax | ||
``` | ||
map.get(key); | ||
``` | ||
**Parameters**: | ||
* **key**: Required. The key of the element to return from the `ReverseIterableMap` object. | ||
**Return value**: | ||
* Returns the element associated with the specified key or `undefined` if the key can't be found in the `ReverseIterableMap` object. | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap(['hey', 'beauty']); | ||
map.get(0); | ||
//> 'hey' | ||
map.get(1); | ||
//> 'beauty' | ||
map.get(2); | ||
//> undefined | ||
``` | ||
### `getLast()` | ||
#### Syntax | ||
``` | ||
map.getLast(); | ||
``` | ||
**Return value**: | ||
* Returns the last element or `null` if the map is empty. | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap(); | ||
map.getLast(); | ||
//> null | ||
map.set('key-chain', 'beauty'); | ||
map.getLast(); | ||
//> 'beauty' | ||
``` | ||
### `getFirst()` | ||
#### Syntax | ||
``` | ||
map.getLast(); | ||
``` | ||
**Return value**: | ||
* Returns the first element or `null` if the map is empty. | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap(); | ||
map.getFirst(); | ||
//> null | ||
map.set('the-magic-key', 'hey'); | ||
map.getFirst(); | ||
//> 'hey' | ||
``` | ||
### `set()` | ||
#### Syntax | ||
``` | ||
map.set(key, value); | ||
``` | ||
**Parameters**: | ||
* **key**: Required. The key of the element to add to the `ReverseIterableMap` object. | ||
* **value**: Required. The value of the element to add to the `ReverseIterableMap` object. | ||
**Return value**: | ||
* The `ReverseIterableMap` object. | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap(); | ||
map.set('key-chain', 'hey'); | ||
//> map | ||
map.set('the-magic-key', 'beauty'); | ||
//> map | ||
``` | ||
The `set()` method returns a reference to the map object. This makes the set operation chainable. | ||
```js | ||
const map = new ReverseIterableMap() | ||
.set('key', '… is spelled like tea') | ||
.set('hey', '… somehow ney'); | ||
``` | ||
### `setFirst()` | ||
The `setFirst()` method functions like `set()` but uses reverse-insertion order. | ||
#### Syntax | ||
``` | ||
map.set(key, value); | ||
``` | ||
**Parameters**: | ||
* **key**: Required. The key of the element to add to the `ReverseIterableMap` object. | ||
* **value**: Required. The value of the element to add to the `ReverseIterableMap` object. | ||
**Return value**: | ||
* The `ReverseIterableMap` object. | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap() | ||
.setFirst('one-t', 'the-magic-key') | ||
.setFirst('featuring', 'cool-t'); | ||
map.getFirst(); | ||
//> 'cool-t' | ||
map.getLast(); | ||
//> 'the-magic-key' | ||
``` | ||
### `delete()` | ||
#### Syntax | ||
``` | ||
map.delete(key); | ||
``` | ||
**Parameters**: | ||
* **key**: Required. The key of the element to remove from the `ReverseIterableMap` object. | ||
**Return value**: | ||
* **Boolean**: Returns `true` if an element in the `ReverseIterableMap` object existed and has been removed, or `false` if the element does not exist. | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap(['hey', 'beauty']); | ||
map.delete(0); | ||
//> true (deletes the key value pair [0, 'hey']) | ||
map.delete(1); | ||
//> true (deletes the key value pair [1, 'beauty']) | ||
map.delete(2); | ||
//> false (key 2 does not exist in map) | ||
``` | ||
### `forEach()` | ||
The `forEach()` method executes a provided function once per each `[key, value]` pair in the `ReverseIterableMap` object, in insertion order. | ||
#### Syntax | ||
``` | ||
map.forEach(callback[, thisArg]); | ||
``` | ||
**Parameters**: | ||
* **callback**: Function to execute for each element. | ||
* **thisArg**: Value to use as `this` when executing `callback`. | ||
**Return value**: | ||
[`undefined`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined). | ||
### `forEachReverse()` | ||
The `forEach()` method executes a provided function once per each `[key, value]` pair in the `ReverseIterableMap` object, in reverse-insertion order. | ||
#### Syntax | ||
``` | ||
map.forEachReverse(callback[, thisArg]); | ||
``` | ||
**Parameters**: | ||
* **callback**: Function to execute for each element. | ||
* **thisArg**: Value to use as `this` when executing `callback`. | ||
**Return value**: | ||
[`undefined`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined). | ||
### `[Symbol.iterator]()` | ||
Returns the map iterator function. By default, this is the `entries()` function. | ||
#### Syntax | ||
``` | ||
map[Symbol.iterator](); | ||
``` | ||
**Return value**: | ||
The map **iterator** function, which is the `entries()` function by default. | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap([1, 2, 4].entries()); | ||
const iterator = map[Symbol.iterator](); | ||
iterator.next().value; | ||
//> 1 | ||
iterator.next().value; | ||
//> 2 | ||
iterator.next().value; | ||
//> 4 | ||
iterator.next().value; | ||
//> undefined | ||
``` | ||
### `reverse()` | ||
In theory, following the semantics of `[Symbol.iterator]()`, this should be `[Symbol.reverseIterator]()`. However, as a developer, I cannot define a well-known symbol myself and make use of it. In the future, the a proposal like [The ReverseIterable Interface, by Lee Byron](https://github.com/leebyron/ecmascript-reverse-iterable) might make it’s way into the specification. For the time being, the `reverse()` function serves the same purpose. | ||
#### Syntax | ||
``` | ||
map.reverse(); | ||
``` | ||
**Return value**: | ||
The map **reverse-iterator** function, which is the `entries().reverse()` function by default. | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap([1, 2, 4].entries()); | ||
const reverseIterator = map.reverse(); | ||
reverseIterator.next().value; | ||
//> 4 | ||
reverseIterator.next().value; | ||
//> 2 | ||
reverseIterator.next().value; | ||
//> 1 | ||
reverseIterator.next().value; | ||
//> undefined | ||
``` | ||
### `entries()` | ||
Returns an iterator containing the `[key, value]` pairs for each element in the `ReverseIterableMap` object in insertion order. | ||
An iterator containing the same pairs in reverse-insertion order can be obtained with `entries().reverse()`. | ||
#### Syntax | ||
``` | ||
map.entries(); | ||
``` | ||
**Return value**: | ||
A new `ReverseIterableMap` iterator object. | ||
### `keys()` | ||
Returns an iterator containing the keys for each element in the `ReverseIterableMap` object in insertion order. | ||
An iterator containing the same keys in reverse-insertion order can be obtained with `keys().reverse()`. | ||
#### Syntax | ||
``` | ||
map.keys(); | ||
``` | ||
**Return value**: | ||
A new `ReverseIterableMap` iterator object. | ||
### `values()` | ||
Returns an iterator containing the values for each element in the `ReverseIterableMap` object in insertion order. | ||
An iterator containing the same values in reverse-insertion order can be obtained with `values().reverse()`. | ||
#### Syntax | ||
``` | ||
map.values(); | ||
``` | ||
**Return value**: | ||
A new `ReverseIterableMap` iterator object. | ||
### `iteratorFor()` | ||
Returns an iterator containing the `[key, value]` pairs for each element in the `ReverseIterableMap` object in insertion order **starting with the pair specified by the `key` parameter**. | ||
This allows starting iteration at a specific element in the map. | ||
An iterator containing the same pairs in reverse-insertion order can be obtained with `iteratorFor().reverse()`. | ||
#### Syntax | ||
``` | ||
map.iteratorFor(key); | ||
``` | ||
**Parameters**: | ||
* **key**: Required. The key of the element to start iterating from. | ||
**Return value**: | ||
A new `ReverseIterableMap` iterator object. | ||
#### Usage | ||
```js | ||
const map = new ReverseIterableMap([1, 2, 4].entries()); | ||
// Iterator, starting at the element with key 1. | ||
const iterator = map.iteratorFor(1); | ||
iterator.next().value; | ||
//> 2 | ||
iterator.next().value; | ||
//> 4 | ||
iterator.next().value; | ||
//> undefined | ||
// Reverse-iterator, starting at the element with key 1. | ||
const reverseIterator = map.iteratorFor(1).reverse(); | ||
reverseIterator.next().value; | ||
//> 2 | ||
reverseIterator.next().value; | ||
//> 1 | ||
reverseIterator.next().value; | ||
//> undefined | ||
``` | ||
## Why this was implemented | ||
Part of the additions to ECMAScript 2015 are the [iteration protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols): [Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol) and [iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol). The former allows arbitrary objects to become iterable. Following the rules of the protocol gives one iteration capabilities via the following techniques: | ||
@@ -88,3 +574,3 @@ | ||
## But why a map? | ||
**But why a map?** | ||
@@ -91,0 +577,0 @@ That’s what I needed. To be precise, I needed to access an iterator _at a specific location_ in my data structure and be able to _iterate in both directions_. |
@@ -135,3 +135,7 @@ export { ReverseIterableMap }; | ||
getLast() { | ||
return this.last.value; | ||
if (this.last) { | ||
return this.last.value; | ||
} | ||
return null; | ||
} | ||
@@ -146,3 +150,7 @@ | ||
getFirst() { | ||
return this.first.value; | ||
if (this.first) { | ||
return this.first.value; | ||
} | ||
return null; | ||
} | ||
@@ -149,0 +157,0 @@ |
Sorry, the diff of this file is not supported yet
42060
818
576