The @temelj/iterator package provides comprehensive utilities for working with iterators, including collection operations, combinatorics, numeric ranges, filtering, searching, and tree traversal.
Installation
npm install @temelj/iterator
Collection operations
collectMap
Collects values from an iterable into a record using a key function.
function collectMap < K extends keyof any , V , V1 = V >(
it : Iterable < V >,
getKey : ( e : V ) => K ,
map ?: ( e : V ) => V1 ,
) : Record < K , V1 >
import { collectMap } from "@temelj/iterator" ;
const users = [
{ id: "1" , name: "Alice" },
{ id: "2" , name: "Bob" },
];
const userMap = collectMap ( users , ( u ) => u . id );
// Result: { "1": { id: "1", name: "Alice" }, "2": { id: "2", name: "Bob" } }
const nameMap = collectMap ( users , ( u ) => u . id , ( u ) => u . name );
// Result: { "1": "Alice", "2": "Bob" }
groupBy
Groups elements from an iterable using a key selector function.
function groupBy < T , K >(
it : Iterable < T >,
getKey : ( item : T ) => K ,
) : Map < K , T []>
import { groupBy } from "@temelj/iterator" ;
const items = [
{ category: "fruit" , name: "apple" },
{ category: "fruit" , name: "banana" },
{ category: "vegetable" , name: "carrot" },
];
const grouped = groupBy ( items , ( item ) => item . category );
// Map {
// "fruit" => [{ category: "fruit", name: "apple" }, { category: "fruit", name: "banana" }],
// "vegetable" => [{ category: "vegetable", name: "carrot" }]
// }
chunk
Splits an iterable into arrays of a specific size.
function chunk < T >( iterable : Iterable < T >, size : number ) : T [][]
import { chunk } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ];
const chunks = chunk ( numbers , 3 );
// Result: [[1, 2, 3], [4, 5, 6], [7]]
window
Yields a sliding window over the iterable.
function window < T >( iterable : Iterable < T >, size : number ) : T [][]
import { window } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 5 ];
const windows = window ( numbers , 3 );
// Result: [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
zip
Combines two iterables into tuples until one is exhausted.
function zip < T , U >( a : Iterable < T >, b : Iterable < U >) : [ T , U ][]
import { zip } from "@temelj/iterator" ;
const names = [ "Alice" , "Bob" , "Charlie" ];
const ages = [ 25 , 30 , 35 ];
const zipped = zip ( names , ages );
// Result: [["Alice", 25], ["Bob", 30], ["Charlie", 35]]
flatten
Flattens nested iterables by one level.
function flatten < T >( iterable : Iterable < Iterable < T > | T >) : T []
import { flatten } from "@temelj/iterator" ;
const nested = [[ 1 , 2 ], [ 3 , 4 ], 5 , [ 6 ]];
const flat = flatten ( nested );
// Result: [1, 2, 3, 4, 5, 6]
unique
Returns a sequence of unique items from an iterable.
function unique < T >(
iterable : Iterable < T >,
identity ?: ( item : T ) => unknown ,
) : T []
Basic uniqueness
With identity function
import { unique } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 2 , 3 , 3 , 3 , 4 ];
const uniqueNumbers = unique ( numbers );
// Result: [1, 2, 3, 4]
Set operations
union
Combines two iterables into a set of unique items from both.
function union < T >( a : Iterable < T >, b : Iterable < T >) : T []
import { union } from "@temelj/iterator" ;
const a = [ 1 , 2 , 3 ];
const b = [ 3 , 4 , 5 ];
const result = union ( a , b );
// Result: [1, 2, 3, 4, 5]
intersection
Returns items present in both iterables.
function intersection < T >( a : Iterable < T >, b : Iterable < T >) : T []
import { intersection } from "@temelj/iterator" ;
const a = [ 1 , 2 , 3 , 4 ];
const b = [ 3 , 4 , 5 , 6 ];
const result = intersection ( a , b );
// Result: [3, 4]
difference
Returns items in the first iterable that are not in the second.
function difference < T >( a : Iterable < T >, b : Iterable < T >) : T []
import { difference } from "@temelj/iterator" ;
const a = [ 1 , 2 , 3 , 4 ];
const b = [ 3 , 4 , 5 , 6 ];
const result = difference ( a , b );
// Result: [1, 2]
Filtering and mapping
filterMap
Filters and maps an iterable in a single pass.
function filterMap < T , U >(
it : Iterable < T >,
filter : ( e : T , i : number ) => U | undefined ,
) : U []
import { filterMap } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 5 ];
const result = filterMap ( numbers , ( n ) => {
if ( n % 2 === 0 ) {
return n * 2 ; // Map even numbers
}
return undefined ; // Filter out odd numbers
});
// Result: [4, 8]
partition
Splits an iterable into two arrays based on a predicate.
function partition < T >(
iterable : Iterable < T >,
predicate : ( item : T ) => boolean ,
) : [ T [], T []]
import { partition } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 5 , 6 ];
const [ evens , odds ] = partition ( numbers , ( n ) => n % 2 === 0 );
// evens: [2, 4, 6]
// odds: [1, 3, 5]
Taking and skipping
take
Takes the first n elements from an iterable.
function take < T >( iterable : Iterable < T >, n : number ) : T []
import { take } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 5 ];
const first3 = take ( numbers , 3 );
// Result: [1, 2, 3]
skip
Skips the first n elements of an iterable.
function skip < T >( iterable : Iterable < T >, n : number ) : T []
import { skip } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 5 ];
const rest = skip ( numbers , 2 );
// Result: [3, 4, 5]
takeWhile
Takes elements while the predicate returns true.
function takeWhile < T >(
iterable : Iterable < T >,
predicate : ( item : T ) => boolean ,
) : T []
import { takeWhile } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 1 , 2 ];
const result = takeWhile ( numbers , ( n ) => n < 4 );
// Result: [1, 2, 3]
skipWhile
Skips elements while the predicate returns true.
function skipWhile < T >(
iterable : Iterable < T >,
predicate : ( item : T ) => boolean ,
) : T []
import { skipWhile } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 5 ];
const result = skipWhile ( numbers , ( n ) => n < 3 );
// Result: [3, 4, 5]
Finding and testing
find
Finds the first element matching a predicate.
function find < T >(
iterable : Iterable < T >,
predicate : ( item : T ) => boolean ,
) : T | undefined
import { find } from "@temelj/iterator" ;
const users = [
{ id: 1 , name: "Alice" },
{ id: 2 , name: "Bob" },
];
const user = find ( users , ( u ) => u . id === 2 );
// Result: { id: 2, name: "Bob" }
any
Checks if any element satisfies the predicate.
function any < T >(
iterable : Iterable < T >,
predicate : ( item : T ) => boolean ,
) : boolean
import { any } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 5 ];
const hasEven = any ( numbers , ( n ) => n % 2 === 0 );
// Result: true
all
Checks if all elements satisfy the predicate.
function all < T >(
iterable : Iterable < T >,
predicate : ( item : T ) => boolean ,
) : boolean
import { all } from "@temelj/iterator" ;
const numbers = [ 2 , 4 , 6 , 8 ];
const allEven = all ( numbers , ( n ) => n % 2 === 0 );
// Result: true
count
Counts elements, optionally matching a predicate.
function count < T >(
iterable : Iterable < T >,
predicate ?: ( item : T ) => boolean ,
) : number
import { count } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 5 ];
const total = count ( numbers );
// Result: 5
Min/max operations
minBy
Finds the minimum element using a selector function.
function minBy < T >(
iterable : Iterable < T >,
selector : ( item : T ) => number ,
) : T | undefined
import { minBy } from "@temelj/iterator" ;
const items = [
{ name: "apple" , price: 1.5 },
{ name: "banana" , price: 0.8 },
{ name: "orange" , price: 1.2 },
];
const cheapest = minBy ( items , ( item ) => item . price );
// Result: { name: "banana", price: 0.8 }
maxBy
Finds the maximum element using a selector function.
function maxBy < T >(
iterable : Iterable < T >,
selector : ( item : T ) => number ,
) : T | undefined
import { maxBy } from "@temelj/iterator" ;
const items = [
{ name: "apple" , price: 1.5 },
{ name: "banana" , price: 0.8 },
{ name: "orange" , price: 1.2 },
];
const expensive = maxBy ( items , ( item ) => item . price );
// Result: { name: "apple", price: 1.5 }
First and last
first
Returns the first element of an iterable.
function first < T >( iterable : Iterable < T >) : T | undefined
import { first } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 ];
const firstNum = first ( numbers );
// Result: 1
last
Returns the last element of an iterable.
function last < T >( iterable : Iterable < T >) : T | undefined
import { last } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 ];
const lastNum = last ( numbers );
// Result: 3
isEmpty
Checks if an iterable is empty.
function isEmpty < T >( iterable : Iterable < T >) : boolean
import { isEmpty } from "@temelj/iterator" ;
const empty = isEmpty ([]);
// Result: true
const notEmpty = isEmpty ([ 1 , 2 , 3 ]);
// Result: false
Numeric ranges
range
Generates a numeric range with configurable step.
function range (
start : number ,
end : number ,
step ?: number ,
) : Generator < number >
Basic range
With step
Descending range
import { range } from "@temelj/iterator" ;
const numbers = Array . from ( range ( 0 , 5 ));
// Result: [0, 1, 2, 3, 4]
parseNumericRange
Parses a string representation of a numeric range.
function parseNumericRange ( s : string ) : NumericRange
import { parseNumericRange , flattenNumericRange } from "@temelj/iterator" ;
const range = parseNumericRange ( "1,3..5,10" );
const values = flattenNumericRange ( range );
// Result: [1, 3, 4, 10]
numericRangeContains
Checks if a numeric range contains a value.
function numericRangeContains (
range : NumericRange ,
value : number ,
) : boolean
import { parseNumericRange , numericRangeContains } from "@temelj/iterator" ;
const range = parseNumericRange ( "1..5,10" );
const contains3 = numericRangeContains ( range , 3 );
// Result: true
const contains7 = numericRangeContains ( range , 7 );
// Result: false
Combinatorics
cartesianProduct
Generates the cartesian product of two iterables.
function cartesianProduct < T , U >(
a : Iterable < T >,
b : Iterable < U >,
) : [ T , U ][]
import { cartesianProduct } from "@temelj/iterator" ;
const colors = [ "red" , "blue" ];
const sizes = [ "S" , "M" , "L" ];
const combinations = cartesianProduct ( colors , sizes );
// Result: [
// ["red", "S"], ["red", "M"], ["red", "L"],
// ["blue", "S"], ["blue", "M"], ["blue", "L"]
// ]
permutations
Generates all permutations of the input iterable.
function permutations < T >( iterable : Iterable < T >) : T [][]
import { permutations } from "@temelj/iterator" ;
const result = permutations ([ 1 , 2 , 3 ]);
// Result: [
// [1, 2, 3], [1, 3, 2],
// [2, 1, 3], [2, 3, 1],
// [3, 1, 2], [3, 2, 1]
// ]
combinations
Generates all combinations of a specific size.
function combinations < T >( iterable : Iterable < T >, n : number ) : T [][]
import { combinations } from "@temelj/iterator" ;
const result = combinations ([ 1 , 2 , 3 , 4 ], 2 );
// Result: [
// [1, 2], [1, 3], [1, 4],
// [2, 3], [2, 4],
// [3, 4]
// ]
Random sampling
sample
Returns a random element from an array.
function sample < T >( array : T []) : T | undefined
import { sample } from "@temelj/iterator" ;
const items = [ "apple" , "banana" , "orange" ];
const randomItem = sample ( items );
// Result: random item from array
sampleList
Returns a list of random samples (with replacement).
function sampleList < T >( array : T [], count : number ) : T []
import { sampleList } from "@temelj/iterator" ;
const items = [ 1 , 2 , 3 , 4 , 5 ];
const samples = sampleList ( items , 3 );
// Result: [2, 5, 2] (example, allows duplicates)
sampleListUnique
Returns a list of random samples without replacement.
function sampleListUnique < T >( array : T [], count : number ) : T []
import { sampleListUnique } from "@temelj/iterator" ;
const items = [ 1 , 2 , 3 , 4 , 5 ];
const samples = sampleListUnique ( items , 3 );
// Result: [2, 5, 1] (example, no duplicates)
arrayShuffle
Shuffles the elements of an array in place.
function arrayShuffle < T >( array : T []) : T []
import { arrayShuffle } from "@temelj/iterator" ;
const numbers = [ 1 , 2 , 3 , 4 , 5 ];
arrayShuffle ( numbers );
// Result: [3, 1, 5, 2, 4] (example, random order)
Array operations
arrayEquals
Compares two arrays for deep equality.
function arrayEquals < T >(
a : T [],
b : T [],
compare ?: ( a : T , b : T ) => boolean ,
) : boolean
import { arrayEquals } from "@temelj/iterator" ;
const equal = arrayEquals ([ 1 , 2 , 3 ], [ 1 , 2 , 3 ]);
// Result: true
const notEqual = arrayEquals ([ 1 , 2 , 3 ], [ 1 , 2 , 4 ]);
// Result: false
arrayBinarySearch
Performs a binary search on a sorted array.
function arrayBinarySearch < T >(
arr : T [],
value : T ,
compare : ( a : T , b : T ) => number ,
) : Result < number , number >
import { arrayBinarySearch } from "@temelj/iterator" ;
import { unwrap , isOk } from "@temelj/result" ;
const numbers = [ 1 , 2 , 3 , 5 , 8 , 13 ];
const result = arrayBinarySearch ( numbers , 5 , ( a , b ) => a - b );
if ( isOk ( result )) {
console . log ( `Found at index ${ unwrap ( result ) } ` );
// Output: "Found at index 3"
}
arrayContainsDuplicates
Checks if an array contains any duplicate elements.
function arrayContainsDuplicates < T >(
arr : T [],
compare ?: ( a : T , b : T ) => boolean ,
) : boolean
import { arrayContainsDuplicates } from "@temelj/iterator" ;
const hasDuplicates = arrayContainsDuplicates ([ 1 , 2 , 3 , 2 ]);
// Result: true
const noDuplicates = arrayContainsDuplicates ([ 1 , 2 , 3 , 4 ]);
// Result: false
Tree traversal
traverseBfs
Traverses a tree structure using breadth-first search.
function traverseBfs < T >(
root : T ,
getChildren : ( node : T ) => Iterable < T >,
) : Generator < T >
import { traverseBfs } from "@temelj/iterator" ;
const tree = {
value: 1 ,
children: [
{ value: 2 , children: [] },
{ value: 3 , children: [{ value: 4 , children: [] }] },
],
};
for ( const node of traverseBfs ( tree , ( n ) => n . children )) {
console . log ( node . value );
}
// Output: 1, 2, 3, 4
traverseDfs
Traverses a tree structure using depth-first search (pre-order).
function traverseDfs < T >(
root : T ,
getChildren : ( node : T ) => Iterable < T >,
) : Generator < T >
import { traverseDfs } from "@temelj/iterator" ;
const tree = {
value: 1 ,
children: [
{ value: 2 , children: [] },
{ value: 3 , children: [{ value: 4 , children: [] }] },
],
};
for ( const node of traverseDfs ( tree , ( n ) => n . children )) {
console . log ( node . value );
}
// Output: 1, 2, 3, 4
The @temelj/iterator package provides lazy evaluation where possible through generator functions, making it memory-efficient for large datasets.