Skip to content

thebopshoobop/iter-range

Repository files navigation

Iterable range

npm version Open Source Love ISC License build status code coverage documentation dependency version status dev dependency version status Code Climate

Quickstart

npm i iter-range
const range = require("iter-range");

for (let i of range(10, 0, -1)) {
  console.log(i);
}
console.log("Midnight!");

range(4).forEach(() => console.log("#winning"));

Introduction

This is just a sweet little range library. It implements the same basic API as the python range function: range([start = 0], stop, [step = 1]). The key differentiator between this library and the other JavaScript range libraries that I have seen is that it does not create and populate arrays with the given parameters. Instead, I provide you a factory function that builds iterable Range objects.

Range objects also include lazily-evaluated implementations of many Array.prototype methods that match their Array counterparts nearly exactly. If you really want an array, you can always use Array.from(range(2, 12)) or the spread operator [...range(5)]. There is also a get method, which will return the value at a given index.

Note that (with the exception of map, reduce, reduceRight, and filter), these are all constant-space methods. They take advantage of the object's iterable nature and don't create any additional arrays or objects. Furthermore, those that accept a callback are written to break early if possible; a some call that matches on the first item stops there and returns. Likewise, indexOf, lastIndexOf, includes, and get are all constant-time operations.

Range

This library exports a single function range, which is a factory for producing Range objects. Range objects are iterable and have a length:

const range = require("iter-range");

for (let i of range(5)) {
  console.log(i); // logs 0, then 1, then 2, etc.
}

// Decreasing and non-integer parameters work a treat:
console.log(...range(27, 8, -4.5)); //=> 27 22.5 18 13.5 9

// The iterator resets when consumed:
const r = range(3);
console.log(...r); //=> 0 1 2
console.log(Array.from(r)); //=> [0, 1, 2]
console.log(...r); //=> 0 1 2

// They have a length property
console.log(range(5).length); //=> 5
console.log(range(0, 10, 3).length); //=> 4

Additionally, Range objects have a whole posse of the standard Array.prototype methods (and get):

const range = require("iter-range");
console.log(range(3, 6).map((i, index) => [i, index])); //=> [[3, 0], [4, 1], [5, 2]]
console.log(...range(5).reverse()); //=> 4 3 2 1 0
console.log(range(8).filter(i => i % 2 === 0)); //=> [0, 2, 4, 6]
console.log(range(2.5, -2.75, -0.25).includes(1)); //=> true
console.log(range(10, 0, -1).indexOf(3)); //=> 7
console.log(range(2.5, 15, 1.25).get(2)); //=> 5

I have strived to match the Array API precisely for these methods. For details, refer to the Range API documentation below.

Exceptions

  • Since these methods don't construct an array to iterate over, there is no array to pass to the callbacks that would normally receive them. Instead they pass the Range object as the third parameter. I hope that's helpful.

  • Reverse does not mutate the Range it is called on, it just returns a new instance.

Development

The Range object methods are thoroughly tested to match their Array.prototype counterparts (except as noted). Please let me know if I've missed or wrongly implemented anything. Jasmine is used for tests, Istanbul is used to ensure complete test coverage, ESLint is used for linting, and jsdoc-to-markdown is used to generate the documentation. You can prepare the dev environment by cloning the repository and installing the dependencies ($ npm i).

  • Tests: npm test
  • Coverage: npm coverage
  • Linting: npm run lint
  • Documentation: npm run doc

API

range([start], stop, [step]) ⇒ Range

Creates a Range instance. Exported.

All of the parameters may be negative or floating point. If you only pass a single parameter, it will be used as stop. In order to pass a step, you must pass all three. In order to create a decreasing Range, you must pass a negative step. If you provide parameters that describe an impossible or empty range, you will receive an object that iterates 0 times.

Kind: global function

Param Type Default Description
[start] number 0 The start of the range. Included.
stop number The end of the range. Excluded.
[step] number 1 The interval to increment by.

Range

Class representing an iterable range of numbers. Not exported.

Kind: global class

range.length : number

The calculated length of the range.

Kind: instance property of Range
Read only: true

range.forEach(callback, [thisArg])

Execute a callback for each element of the range.

Kind: instance method of Range

Param Type Default Description
callback iterCallback The function to call for each element.
[thisArg] any this The object that this will refer to inside the callback.

range.map(callback, [thisArg]) ⇒ array

Build an array with the return values of a function called for each element of the range.

Kind: instance method of Range

Param Type Default Description
callback iterCallback The function to call for each element.
[thisArg] any this The object that this will refer to inside the callback.

range.reduce(callback, [accumulator]) ⇒ any

Apply a function to an accumulator and each element in the range to reduce it to a single value.

Kind: instance method of Range
Throws:

  • TypeError - If given an empty range and accumulator.
Param Type Description
callback reduceCallback The function to call for each element.
[accumulator] any The initial value for the accumulator. If no accumulator is given, the first element in the array will be used.

range.reduceRight(callback, [accumulator]) ⇒ any

Apply a function to an accumulator and each element in the range in reverse order to reduce it to a single value.

Kind: instance method of Range
Throws:

  • TypeError - If given an empty range and accumulator.
Param Type Description
callback reduceCallback The function to call for each element.
[accumulator] any The initial value for the accumulator. If no accumulator is given, the last element in the array will be used.

range.every(callback, [thisArg]) ⇒ boolean

Apply a function to an each element in the range, returning true if every function call does.

Kind: instance method of Range

Param Type Default Description
callback iterCallback The function to call for each element.
[thisArg] any this The object that this will refer to inside the callback.

range.some(callback, [thisArg]) ⇒ boolean

Apply a function to an each element in the range, returning true if at least one function call does.

Kind: instance method of Range

Param Type Default Description
callback iterCallback The function to call for each element.
[thisArg] any this The object that this will refer to inside the callback.

range.filter(callback, [thisArg]) ⇒ array

Apply a function to an each element in the range, returning an array populated with the elements for which the function call returns true.

Kind: instance method of Range

Param Type Default Description
callback iterCallback The function to call for each element.
[thisArg] any this The object that this will refer to inside the callback.

range.find(callback, [thisArg]) ⇒ any

Apply a function to an each element in the range, returning the first element for which the function call returns true.

Kind: instance method of Range

Param Type Default Description
callback iterCallback The function to call for each element.
[thisArg] any this The object that this will refer to inside the callback.

range.findIndex(callback, [thisArg]) ⇒ number

Apply a function to an each element in the range, returning the index of first element for which the function call returns true.

Kind: instance method of Range

Param Type Default Description
callback iterCallback The function to call for each element.
[thisArg] any this The object that this will refer to inside the callback.

range.indexOf(searchElement, [fromIndex]) ⇒ number

Return the index of the first instance of the given element or -1.

Kind: instance method of Range

Param Type Default Description
searchElement number The number to search for.
[fromIndex] number 0 The smallest acceptable index. If the value is greater than the length of the range, -1 will be returned. Negative indexes are treated as indexes from the right side of the range. If the calculated index is less than 0, the whole range will be considered.

range.lastIndexOf(searchElement, [fromIndex]) ⇒ number

Return the index of the last instance of the given element or -1.

Kind: instance method of Range

Param Type Default Description
searchElement number The number to search for.
[fromIndex] number 0 The largest acceptable index. If the value is greater than the length of the range, the whole range will be considered. Negative indexes are treated as indexes from the right side of the range. If the calculated index is less than 0, -1 will be returned.

range.includes(searchElement, [fromIndex]) ⇒ boolean

Return true if the Range contains the given element or -1.

Kind: instance method of Range

Param Type Default Description
searchElement number The number to search for.
[fromIndex] number 0 The smallest acceptable index. If the value is greater than the length of the range, false will be returned. Negative indexes are treated as indexes from the right side of the range. If the calculated index is less than 0, the entire range will be considered.

range.reverse() ⇒ Range

Returns a new instance of Range that will produce the range in reversed order.

Kind: instance method of Range

range.get(index) ⇒ number

Return the value at a given index.

Kind: instance method of Range
Throws:

  • TypeError - If the index is out of bounds.
Param Type Description
index number The index to query. Negative indexes will be treated as indexes from the end of the range.

iterCallback : function

The function signature for the callbacks passed to the forEach, map, every, some, filter, find, and findIndex methods.

Kind: global typedef

Param Type Description
currentValue number The current element of the range.
index number The index of the current element.
range Range The current Range object.

Example

const callback = function(currentValue, index, range) {
  // perform some action
}
range(10, 0, -1).forEach(callback);

Example

range(5).map(currentValue => currentValue ** 2);

reduceCallback : function

The function signature for the callbacks passed to the reduce and reduceRight methods.

Kind: global typedef

Param Type Description
accumulator any The accumulated results of the reduction.
currentValue number The current element of the range.
index number The index of the current element.
range Range The current Range object.

Example

const callback = function(accumulator, currentValue, index, range) {
  // return accumulated value
}
range(12).reduce(callback);

Example

range(5).reduce((accumulator, currentValue) => accumulator + currentValue);

About

An iterable range library that's here for you.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published