{"id":20858681,"url":"https://github.com/thesephist/ittr","last_synced_at":"2025-12-26T16:52:43.675Z","repository":{"id":57278629,"uuid":"166935341","full_name":"thesephist/ittr","owner":"thesephist","description":"Small library of iterator-related utility functions for JavaScript","archived":false,"fork":false,"pushed_at":"2019-01-23T05:41:16.000Z","size":90,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-26T08:41:34.289Z","etag":null,"topics":["functional-programming","iterator","nodejs"],"latest_commit_sha":null,"homepage":"https://thesephist.github.io/ittr/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thesephist.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-22T05:52:42.000Z","updated_at":"2021-03-23T21:14:28.000Z","dependencies_parsed_at":"2022-09-09T14:10:42.928Z","dependency_job_id":null,"html_url":"https://github.com/thesephist/ittr","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thesephist%2Fittr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thesephist%2Fittr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thesephist%2Fittr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thesephist%2Fittr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thesephist","download_url":"https://codeload.github.com/thesephist/ittr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243230101,"owners_count":20257644,"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":["functional-programming","iterator","nodejs"],"created_at":"2024-11-18T04:46:57.902Z","updated_at":"2025-12-26T16:52:43.634Z","avatar_url":"https://github.com/thesephist.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ittr\n\n[![npm ittr](https://img.shields.io/npm/v/ittr.svg)](http://npm.im/ittr)\n[![Build Status](https://travis-ci.com/thesephist/ittr.svg?branch=master)](https://travis-ci.com/thesephist/ittr)\n[![gzip size](http://img.badgesize.io/https://unpkg.com/ittr/dist/index.min.js?compression=gzip)](https://unpkg.com/ittr/dist/index.min.js)\n\nSmall library of iterator-related utility functions for JavaScript.\n\n**Fully annotated source**: [GitHub Pages](https://thesephist.github.io/ittr/src/index.js.html).\n\nIttr doesn't try to be a comprehensive hub of all array methods -- there are lots of NPM libraries will do that very well. This is just a smaller collection of just the essential (by my definition of _essential_) array/iterator methods I've learned comes up very, very often in UI development, including many that aren't a part of the JavaScript standard.\n\n## Features\n\n- **Works with any JavaScript iterator, not just arrays**\n- Nice API\n- Tiny, simple to use\n- Relatively fast, compared to native JavaScript array methods\n\n## Usage\n\nImport it with a `\u003cscript\u003e` tag...\n\n```html\n\u003cscript src=\"https://unpkg.com/ittr/dist/index.min.js\"\u003e\u003c/script\u003e\n```\n\n... and you'll find all the API functions exposed under the `Ittr` global object.\n\nYou can also `npm install ittr`, which will allow you to use it in both Node.js and client-side projects.\n\nPlease see the [documentation](https://thesephist.github.io/ittr/src/index.js.html) for detailed API information.\n\n### Build and test\n\nYou can build step with `npm build`, and run unit tests in `test/tests.js` with `npm test`.\n\n## API documentation\n\n`ittr` works with iterables in its own representation, to allow chaining calls. Create an Ittr object from a JavaScript iterable (generators, arrays, custom iterators) with the `iter()` function.\n\n```javascript\nconst arr = [1, 2, 3, 4, 5];\nconst myIterable = iter(arr);\n```\n\nWe can convert the Ittr object back to an array using `iter.toArray()`, or by iterating through them.\n\n```javascript\nmyIterable.toArray();\n// [1, 2, 3, 4, 5]\n\n[...myIterable]\n// [1, 2, 3, 4, 5]\n\nconst arr2 = []\nfor (const x of myIterable) {\n    arr2.push(x);\n}\n// arr == [1, 2, 3, 4, 5]\n```\n\n`iter` has a variety of commonly used list methods with reasonable defaults.\n\n### `iter.map(predicate)`\n\n```javascript\niter([1, 2, 3, 4, 5]).map(x =\u003e x * x).toArray();\n// [1, 4, 9, 16, 25]\n```\n\nMap over each item in the iterator.\n\nReturns a new `iter` object, where the `predicate` was called with each each item in the iterator. The behavior is conceptually similar to native `Array.prototype.map`.\n\n### `iter.filter(predicate)`\n\n```javascript\niter([1, 2, 3, 4, 5]).filter(x =\u003e x % 2).toArray();\n// [1, 3, 5]\n```\n\nFilter the iterator's items with a given predicate function.\n\nReturns a new `iter` object that only contains items from the original iterator, where passing it into the predicate function yielded a truthy value.\n\nIf the `predicate` is omitted, an identity function (`x =\u003e x`) will be used by default. This allows you to write `iter(arr).filter()` to filter out falsy values.\n\n### `iter.reduce(predicate, initial)`\n\n```javascript\niter([1, 2, 3, 4, 5]).reduce((last, cur) =\u003e last * cur);\n// 25, because 1 * 2 * 3 * 4 * 5 == 25\n```\n\nReduce from the left over the iterator, with a given `predicate` and initial value.\n\nThe behavior is conceptually similar to the native `Array.prototype.reduce`.\n\n### `iter.every(predicate)`\n\n```javascript\niter([1, 2, 3, 4, 5]).every(x =\u003e x \u003e 0);\n// true\n\niter([1, 2, 3, 4, 5]).every(x =\u003e x % 2 === 0);\n// false\n\niter([true, true, true, true]).every();\n// true\n```\n\nReports true only if calling the `predicate` function with every item in the iterator returns a truthy value. If called with an empty iterator, it returns true;\n\nIf no `predicate` function is passed, it'll default to the identity function (`x =\u003e x`);\n\n### `iter.some(predicate)`\n\n```javascript\niter([1, 2, 3, -4, -5]).some(x =\u003e x \u003e 0);\n// true\n\niter([1, 2, 3, 4, 5]).some(x =\u003e x \u003c 0);\n// false\n\niter([true, true, true, false]).some();\n// true\n```\n\nReports true if calling the `predicate` with one or more item(s) of the iterator returns a truthy value. If called with an empty iterator, it returns false.\n\nIf no `predicate` function is passed, it'll default to the identity function (`x =\u003e x`);\n\n### `iter.flatMap(predicate)`\n\n```javascript\nconst strings = ['foo bar', 'baz', 'hello javascript world'];\niter(strings).flatMap(str =\u003e str.split(' ')).toArray();\n// ['foo', 'bar', 'baz', 'hello', 'javascript', 'world']\n\niter([[1, 2], [3], [4, 5, 6]]).flatMap();\n// [1, 2, 3, 4, 5, 6]\n```\n\n`flatMap()` returns a new `iter` object. From each item in the original iterator, the predicate is called on each item, and the returned array is concatenated into the resulting list. This results in an effective map, then \"flattening\" with a depth of 1.\n\nWhen the `predicate` function is not specified, an identity function (`x =\u003e x`) is used.\n\n`iter.flatMap()` also obviates the need for a `iter.flatten()`, since calling `flatMap()` with no arguments or an identity function will just flatten the array to a depth of 1. (If you don't know how deep your arrays are nested, you either 1. will benefit from writing a more custom function or 2. should consider restructuring your code to be more deterministic.)\n\n### `iter.partition(maxSize)`\n\n```javascript\niter([1, 2, 3, 4, 5, 6, 7, 8]).partition(3).toArray();\n// [[1, 2, 3], [4, 5, 6], [7, 8]]\n```\n\nReturns a new `iter` object, where each item is an array containing `maxSize` number of items from the original iterator, in order from the original iterator. If there are any items \"left over\", the last item in the returned iterator may have less than `maxSize` number of items.\n\n### `iter.sortBy(predicate)`\n\n```javascript\niter([\n    {age: 3},\n    {age: 15},\n    {age: 9},\n]).sortBy(obj =\u003e obj.age).toArray();\n// [\n//     {age: 3},\n//     {age: 9},\n//     {age: 15},\n// ]\n```\n\nReturns a new `iter` object containing all the items from the original iterator, sorted by the comparator that `predicate` returns when it's called with each item. Internally, it just uses `Array.prototype.sort`.\n\nWhen no `predicate` is specified, it defaults to the identity function, which results in identical behavior to `Array.prototype.sort`.\n\n### Chaining `iter` methods\n\nBecause each `iter` method call returns another `iter` object, we can chain method calls together to easily perform sophisticated list manipulations.\n\n```javascript\niter(range(2, 20))\n    .filter(x =\u003e x % 2 === 0) // only evens, [2 .. 18]\n    .partition(3) // group by 3, [[2, 4, 6], [8, 10, 12], ...]\n    .map(([a, b, c]) =\u003e `${a} \u003c ${b} \u003c ${c}`)\n    .toArray().join(', ');\n// '2 \u003c 4 \u003c 6, 8 \u003c 10 \u003c 12, 14 \u003c 16 \u003c 18'\n\niter(users)\n    .filter(user =\u003e user.isAdmin)\n    .sortBy(user =\u003e user.name)\n    .map(user =\u003e new UserView(user))\n    .partition(2)\n    .toArray();\n// list of admin user views, sorted by name, grouped into pairs\n```\n\n### `range(start [, end [, step]])`\n\n```javascript\n// one argument\nrange(5);\n// [0, 1, 2, 3, 4]\n\n// two arguments\nrange(2, 8.5);\n// [2, 3, 4, 5, 6, 7, 8]\n\n// three arguments\nrange(0, 3, 0.5);\n// [0, .5, 1, 1.5, 2, 2.5]\n```\n\n`range()` is conceptually identical to Python's `range()` function. It's variadic and has three modes.\n\n1. `range(start, end, step)`: Return an array of numbers, starting with `start`, and adding `step` each time, until the value exceeds `end`. The returned array never incldues a value equal to or greater than `end`.\n2. `range(start, end)`: When `step` is omitted, it's assumed to be 1.\n3. `range(end)`: When `start` is omitted, it's assumed to be 0. This means calling `range(n)` where `n` is a positive integer results in an array of length `n`, with increasing integer items.\n\n### `zip(...arrays)`\n\n```javascript\nzip(\n    [1, 2, 3],\n    ['a', 'b', 'c'],\n    ['X', 'Y', 'Z']\n);\n//  [\n//     [1, 'a', 'X'],\n//     [2, 'b', 'Y'],\n//     [3, 'c', 'Z'],\n// ]\n```\n\n`zip()` is conceptually identical to Python's `zip()`. Given a variable number of arrays, it returns an array whose length is equal to the length of the longest array given to it. In the returned array, the `n`th item is an array with the `n`th item from each argument array, in order.\n\n`zip()` can also be called with a spread array (`...someArray`) to \"unzip\" a zipped array into its parts.\n\n```javascript\nconst zippedArray = [\n    [1, 'a', 'X'],\n    [2, 'b', 'Y'],\n    [3, 'c', 'Z'],\n];\nzip(...zippedArray);\n// [\n    // [1, 2, 3],\n    // ['a', 'b', 'c'],\n    // ['X', 'Y', 'Z'],\n// ]\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthesephist%2Fittr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthesephist%2Fittr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthesephist%2Fittr/lists"}