{"id":17520850,"url":"https://github.com/hillc5/iterable-range","last_synced_at":"2025-03-28T23:26:26.411Z","repository":{"id":48032356,"uuid":"141645491","full_name":"hillc5/iterable-range","owner":"hillc5","description":"Range iterator with helper functions and a growing library of operations for iterables in general","archived":false,"fork":false,"pushed_at":"2022-12-07T10:36:41.000Z","size":453,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-05T02:16:25.093Z","etag":null,"topics":["combine","distinct","filter","iterable","iterable-extensions","javascript","lazy-evaluation","limit","map","operators","range","takeuntil","zip"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hillc5.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-20T00:54:14.000Z","updated_at":"2024-01-24T03:17:49.000Z","dependencies_parsed_at":"2023-01-24T16:45:50.466Z","dependency_job_id":null,"html_url":"https://github.com/hillc5/iterable-range","commit_stats":null,"previous_names":["hillc5/range-iterator"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hillc5%2Fiterable-range","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hillc5%2Fiterable-range/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hillc5%2Fiterable-range/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hillc5%2Fiterable-range/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hillc5","download_url":"https://codeload.github.com/hillc5/iterable-range/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246114404,"owners_count":20725616,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["combine","distinct","filter","iterable","iterable-extensions","javascript","lazy-evaluation","limit","map","operators","range","takeuntil","zip"],"created_at":"2024-10-20T11:42:02.634Z","updated_at":"2025-03-28T23:26:26.390Z","avatar_url":"https://github.com/hillc5.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/hillc5/iterable-range.svg?branch=master)](https://travis-ci.org/hillc5/iterable-range)\n\n# iterable-range\nThe iterable-range module provides iterable range creation functionality with a number of helper methods.  Created ranges are lazily evaluated and thus all transforms/modifiers are applied only as needed.  Created ranges include the start but not the end values supplied in the parameters\n\n# Contents\n* [Installation](#installation)\n* [Usage](#usage)\n  * [Quick creation](#quick-creation)\n  * [Using *step* parameter](#using-step-parameter)\n  * [Replay-ability](#replay-ability)\n  * [Import with CommonJS](#import-using-commonjs)\n* [Methods](#methods)\n  * [map](#map)\n  * [filter](#filter)\n  * [limit](#limit)\n  * [reverse](#reverse)\n  * [takeUntil](#takeUntil)\n  * [contains](#contains)\n  * [length](#length)\n* [Operators](#operators)\n  * [combine](#combine)\n  * [concat](#concat)\n  * [zip](#zip)\n  * [distinct](#distince)\n\n# Installation\n```bash\nnpm i --save iterable-range\n```\n\n# Usage\n**range(*start*, *end*, *step[optional]*)**\n\n### Quick creation\n```javascript\nimport range from 'iterable-range';\n\nconst r = range(1, 5);\n\nfor (let x of r) {\n    console.log(x)  // Prints 1 2 3 4\n}\n\n[...r] // [1, 2, 3, 4]\n\nconst r2 = range(5) // Single argument, defaults initial value to 0\n\n[...r2] // [0, 1, 2, 3, 4]\n\n```\n\n\n### Using *step* parameter\n```javascript\nimport range from 'iterable-range';\n\nconst r = range(1, 10, 2);\n\n[...r]           // [1, 3, 5 ,7, 9]\n[...r.reverse()] // [9, 7, 5, 3, 1]\n\nconst r2 = range(10, -10, -5);\n\n[...r2]              // [10, 5, 0, -5]\n[...r2.reverse()]    // [-5, 0, 5, 10]\n```\n\n### Replay-ability\nAn iterable range can be re-ran an infinite number of times, producing the same values each time.  A normal iterator will only be able to be ran once, producing the *done* for any subsequent runs after the first.  A range will\njust re-run as if it was just initialized.\n```javascript\nimport range from 'iterable-range';\n\nconst r = range(0, 100, 20);\n[...r] // [0, 20, 40, 60, 80];\n[...r] // [0, 20, 40, 60, 80];\n...\n...\n[...r] // You get the idea\n```\n\n### Import using CommonJS\n```javascript\n// For commonjs (for now)\nconst range = require('iterable-range').default\nconst { concat, zip, distinct } = require('iterable-range');\n```\n\n# Methods\nEvery method applied to an iterable range returns a new iterable range, preserving the original.\n```javascript\nconst r = range(1, 5);\n\n[...r] // [1, 2, 3, 4]\n\nconst r2 = r.map(val =\u003e val * -1);\n\n[...r2] // [-1, -2, -3, -4]\n[...r] // [1, 2, 3, 4]\n\n```\n\n\n###  map \n**Parmeters: *mapFn*** - The function to be applied to each viable value in the range.  \nMapfn is supplied with just the value to be acted upon\n\n```javascript\nconst r = range(1, 5);\n\n[...r.map(val =\u003e val * val)] // [1, 4, 9, 16]\n\n// Can have multiple applications\n\n[...r.map(val =\u003e val * val).map(val =\u003e val % 2 === 0 ? 0 : 1)] // [1, 0, 1, 0]\n\n// Works as expected when a step value is provided\nconst rWithStep = range(1, 10, 2);\n\n[...rWithStep]                        // [1, 3, 5, 7, 9]\n[...rWithStep.map(val =\u003e val * val)]  // [1, 9, 25, 49, 81]\n\n```\n\n### filter\n**Parameters: *filterFn*** - The function to be applied to each vialb value in the range.  \nIf filterFn returns *falsy* for any given value then that value will not appear in the next chained method, and will effectively be removed from the range.  Filterfn is supplied with just the value to be acted upon\n\n```javascript\nconst r = range(1, 5);\n\n[...r.filter(val =\u003e val % 2)] // [1, 3]\n\n// Can be chained before or after map function\n\n[...r.map(val =\u003e val * val).filter(val =\u003e val % 2)] // [1, 9]\n[...r.filter(val =\u003e val % 2).map(val =\u003e val * val)] // [1, 9]\n\n```\n\n\n### limit\n**Parameters: *limitVal*** - The number of elements to be produced by the range and it's transform chain.  \nThe limit method can appear in any place in the range transform chain, and if multiple calls are made, the last call will be the used value\n\n```javascript\nconst r = range(1, Infinity)  // Will run for ever if used without .limit(limitVal)\n\n[...r.limit(5)] // [1, 2, 3, 4, 5]\n[...r.limit(5).limit(10)] // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n[...r.map(val =\u003e val * val).filter(val =\u003e val % 2).limit(100)] // Will produce the first 100 odd square numbers\n\n```\n\n### reverse\nReverses the output from the range iterable.  It can be called anywhere in the transform chain, but multiple calls will not negate one another -- Once reverse is called output will always be reversed.\n\n```javascript\nconst r = range(1, 10);\n\n[...r.reverse()] // [9, 8, 7, 6, 5, 4, 3, 2, 1]\n\n[...r.map(val =\u003e val * val).limit(5).reverse()] // [25, 16, 9, 4 ,1]\n\n// if step is provided reverse still returns the exact reverse of the normal output\n\nconst rWithStep = range(-20, 42, 7);\n\n[...rWithStep]              // [-20, -13, -6, 1, 8, 15, 22, 29, 36]\n[...rWithStep.reverse()]    // [36, 29, 22, 15, 8, 1, -6, -13, -20]\n\n```\n\n### takeUntil\n**Parameters: *takeUntilFn*** - A function that indicates when the range iterator should stop producing values.  \n\nIf takeUntilFn returns *truthy* for any value then the range iterator will disregard that value and stop producing values.  \n\n**Note** No matter where the .takeUntil method is called, it will be applied after all transforms have been applied to any value.\n\n```javascript\nconst r = range(1, 10);\n\n[...r.takeUntil(val =\u003e val \u003e 6)] // [1, 2, 3, 4, 5, 6]\n[...r.takeUntil(val =\u003e val === 25).map(val =\u003e  val * val)] // [1, 4, 9, 16]\n\n```\n\n\n### contains\n**Parameters: *num*** - Number to check whether it will be produced by the base range iterable.  \n\ncontains will produce true or false if the given num is going to be produced by the initially created range (the range that has not had any other method applied to it).  This is done in constant *O(1)* time and does not iterate over the produced range, or store anything in another data structure in order to determine if the value will be produced\n\n```javascript\nconst r1 = range(10);\nr1.contains(3)  // true\nr1.contains(10) // false\n\nconst r2 = range(-10);\nr2.contains(-3)  // true\nr2.contains(-10) // false\nr2.contains(3)   // false\n\nconst r3 = range(-10, 10, 5);\nr3.contains(-10)  // true\nr3.contains(-8)   // false\nr3.contains(0)    // true\nr3.contains(10)   // false\n\n```\n\n\n### length\nReturns the number of values that will be produced by the base range iterable.  Calling length will return the number of items that will be produced.  This is done in constant *O(1)* time and does not iterate over the values, or store them in another data structure to determine the length\n\n```javascript\nconst r1 = range(1, 10);\nr1.length()  // 9\n\nconst r2 = range(10);\nr2.length()  // 10\n\nconst r3 = range(1, 20, 2);\nr3.length()  // 10\n\nconst r4 = range(-10, -32, -3);\nr4.length()  // 8\n\nconst r5 = range(1, Infinity);\nr5.length()  // Infinity\n\n```\n\n# Operators\nOperators are added utility methods that may or may not be restricted to usage with iterable ranges.\n\n### combine\n**Parameters: *iters*** - Array of iterables  \n**Parameters: *combineFn*** - function that maps from an array of values, to some other value(s)  \n**Throws: *TypeError*** - if **iters** is not an array  \n**Throws: *TypeError*** - if any element in **iters** is not an iterable  \n\ncombine takes an array of iterables and produces a new iterable that combines the values from each iterable, either as an array of each value from each iterable, or as a new value that has been mapped by the given combineFn.  The values that are stored in the returned array represent the value that is produced by each given iterable at that position in its iterator.  \n\nThe given **combineFn** will be passed the array of combined values, and can return any output that it desires.\n\n```javascript\nconst iter1 = [1, 2, 3];\nconst iter2 = [4, 5, 6];\n\nconst iters = [iter1, iter2];\n\n[...combine(iters)] // [[1, 4], [2, 5], [3, 6]]\n\nconst sum = values =\u003e values.reduce((result, value) =\u003e result + value, 0);\n\n[...combine(iters, sum)] // [5, 7, 9];\n\n```\n\n### concat\n**Parameters: *...Iterable(s)*** -  Any number of iterables.  \n**Throws: *TypeError*** - If any given argument is not an iterable.  \n \nconcat returns an iterable that will produce values from each iterator.  The values produced will be from only one iterable at a time, until it has been exhausted.  The ordering will be in the same order that the iterables are provided  \n\n```javascript\nimport range, { concat } from 'iterable-range';\n\nconst r1 = range(0, 10, 2);\nconst r2 = range(8, -1, -2);\n\n[...concat(r1, r2)]  // [0, 2, 4, 6, 8, 8, 6, 4, 2, 0]\n\n\nconst iter1 = 'hello ';\nconst iter2 = 'world';\n\n[...concat(iter1, iter2)] // ['h', 'e', 'l', 'l'. 'o', ' ', 'w', 'o', 'r', 'l', 'd'];\n\n```\n\n\n### zip\n**Parameters: *...Iterable(s)*** - Any number of iterable(s).  \n**Throws: *TypeError*** - If any given argument is not an iterable.  \n\nzip returns an iterable that will produce the interleaved values of the provided iterables.  It will produce its values from the iterables in the order that they are passed into the function.  It will continue to produce values until all given iterables have exhausted there values.\n\n**Note** The iterable returned by the zip function will only produce values one time.  Any subsequent call after the initial call will return *{ done: true }*\n**Note** Any iterables passed in that are not *replay-able* will also be exhausted\n\n```javascript\nimport range, { zip } from 'iterable-range';\n\nconst r1 = range(1, 10, 2);\nconst r2 = range(1, 20, 4);\n\n[...zip(r1, r2)] // [1, 1, 3, 5, 5, 9, 7, 13, 9, 17]\n\nconst i1 = [1, 2, 3, 4];\nconst i2 = [4, 3, 2, 1];\n\n[...zip(i1, i2)] // [1, 4, 2, 3, 3, 2, 4, 1];\n\nconst i3 = [1, 2, 3, 4, 6, 6, 6];\n\n[...zip(i3, i2)] // [1, 4, 2, 3, 3, 2, 4, 1, 6, 6, 6];\n\n```\n\n### distinct\n**Parameters: *Iterable*** - Any item that implements the iterable protocol  \n**Throws: *TypeError*** - If parameter does not implement the iterable protocol  \n\ndistinct returns an iterable that will produce only unique values.  Any duplicates found in the given iterable will only be returned once, all others will be discarded.\n\n**Note** distinct will exhaust any non-replayable iterable that is operated on.  \n**Note** distinct uses a Set internally and could potentially use memory-space O(m) (m = total number of produced values)\n\n```javascript\nimport range, { zip, distinct } from 'iterable-range';\n\nconst r1 = range(1, 20, 2);\nconst r2 = range(1, 20, 4);\nconst z = zip(r1, r2);\n\n[...distinct(z)] // [1, 3, 5, 9, 7, 13, 17, 11, 15, 19]\n\n[...distinct('Hello World!')] // ['H', 'e', 'l', 'o', ' ', 'W', 'r', 'd', '!']\n\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhillc5%2Fiterable-range","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhillc5%2Fiterable-range","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhillc5%2Fiterable-range/lists"}