'use strict'; export namespace Iterables { export function every(source: Iterable | IterableIterator, predicate: (item: T) => boolean): boolean { for (const item of source) { if (!predicate(item)) return false; } return true; } export function* filter(source: Iterable | IterableIterator, predicate: (item: T) => boolean): Iterable { for (const item of source) { if (predicate(item)) yield item; } } export function* filterMap(source: Iterable | IterableIterator, predicateMapper: (item: T) => TMapped | undefined | null): Iterable { for (const item of source) { const mapped = predicateMapper(item); if (mapped) yield mapped; } } export function forEach(source: Iterable | IterableIterator, fn: (item: T, index: number) => void): void { let i = 0; for (const item of source) { fn(item, i); i++; } } export function find(source: Iterable | IterableIterator, predicate: (item: T) => boolean): T | null { for (const item of source) { if (predicate(item)) return item; } return null; } export function first(source: Iterable): T { return source[Symbol.iterator]().next().value; } export function* flatMap(source: Iterable | IterableIterator, mapper: (item: T) => Iterable): Iterable { for (const item of source) { yield* mapper(item); } } export function has(source: Iterable | IterableIterator, item: T): boolean { return some(source, _ => _ === item); } export function isIterable(source: Iterable): boolean { return typeof source[Symbol.iterator] === 'function'; } export function join(source: Iterable, separator: string): string { let value = ''; const iterator = source[Symbol.iterator](); let next = iterator.next(); if (next.done) return value; while (true) { const s = next.value.toString(); next = iterator.next(); if (next.done) { value += s; break; } value += `${s}${separator}`; } return value; } export function last(source: Iterable): T | null { let item: T | null = null; for (item of source) { /* noop */ } return item; } export function* map(source: Iterable | IterableIterator, mapper: (item: T) => TMapped): Iterable { for (const item of source) { yield mapper(item); } } export function next(source: IterableIterator): T { return source.next().value; } export function* skip(source: Iterable | IterableIterator, count: number): Iterable | IterableIterator { let i = 0; for (const item of source) { if (i >= count) yield item; i++; } } export function some(source: Iterable | IterableIterator, predicate: (item: T) => boolean): boolean { for (const item of source) { if (predicate(item)) return true; } return false; } export function* take(source: Iterable | IterableIterator, count: number): Iterable { if (count > 0) { let i = 0; for (const item of source) { yield item; i++; if (i >= count) break; } } } export function* union(...sources: (Iterable | IterableIterator)[]): Iterable { for (const source of sources) { for (const item of source) { yield item; } } } }