/** Returns a tuple consisting of a running index starting from 0, and the item of the iterable */ export function* enumerate(iterable: Iterable) { let index = 0; for (const item of iterable) { yield [index++, item] as [number, T]; } } /** Filters an iterable based on the passed predicate function */ export function* filter(it: Iterable, predicate: (value: T) => value is S) { for (const value of it) { if (predicate(value)) { yield value; } } } /** Converts a name to an id */ export function toId(name: string) { return name.toLowerCase().replace(/[^a-z0-9]+/g, "-"); } /** Returns adjacent pairs from iterable */ export function* pairs(iterable: Iterable) { let first; let second; for (const [index, item] of enumerate(iterable)) { [first, second] = [second, item]; if (index >= 1) { yield [first, second] as [T, T]; } } } /** Returns true if all sets are equal @param sets set to compare @returns true if all sets are the same size and have the same elements */ export function setEquals(...sets: Set[]) { if (sets.length < 2) { throw TypeError("At least two sets must be passed to setEquals"); } const ref = sets[0]; const rest = sets.slice(1); if (rest.some(set => set.size !== ref.size)) { return false; } for (const set of rest) { for (const el of set) { if (!ref.has(el)) { return false; } } } return true; }