I firmly believe in free software. The application I'm making here have capabilities that I've not seen in any system. It presents itself as an opportunity to collaborate on a tool that serves the people rather than corporations. Whose incentives are to help people rather, not make the most money. And whose terms ensure that these freedoms and incentives cannot be taken back or subverted. I license this software under the AGPL.
109 lines
2.7 KiB
TypeScript
109 lines
2.7 KiB
TypeScript
/*
|
|
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
/** Returns a tuple consisting of a running index starting from 0, and the item of the iterable */
|
|
export function* enumerate<T>(iterable: Iterable<T>) {
|
|
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<T, S extends T>(it: Iterable<T>, predicate: (value: T) => value is S): Generator<S, void, unknown>;
|
|
export function filter<T>(it: Iterable<T>, predicate: (value: T) => unknown): Generator<T, void, unknown>;
|
|
export function* filter(it: Iterable<unknown>, predicate: (value: unknown) => unknown): Generator<unknown, void, unknown> {
|
|
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<T>(iterable: Iterable<T>) {
|
|
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 the two arrays passed as input compare equal to each other.
|
|
@param a Input array
|
|
@param b Input array
|
|
@param equals Function to compare individual elements in the array.
|
|
@returns True if the arrays compare equal
|
|
*/
|
|
export function arrayEquals<T>(
|
|
a: T[],
|
|
b: T[],
|
|
equals: (a: T, b: T) => unknown = (a, b) => a === b,
|
|
) {
|
|
if (a.length !== b.length) {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < a.length; i++) {
|
|
if (!equals(a[i], b[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
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<T>(...sets: Set<T>[]) {
|
|
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;
|
|
}
|
|
|
|
/**
|
|
Returns true if the two maps passed as input compare equal to each other.
|
|
@param a Input map
|
|
@param b Input map
|
|
@param equals Function to compare individual values in the map.
|
|
@returns True if the maps compare equal
|
|
*/
|
|
export function mapEquals<K, V>(
|
|
a: Map<K, V>,
|
|
b: Map<K, V>,
|
|
equals: (a: V, b: V) => unknown = (a, b) => a === b,
|
|
) {
|
|
if (a.size !== b.size) {
|
|
return false;
|
|
}
|
|
for (const [key, value] of a) {
|
|
if (!b.has(key) || value !== b.get(key)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|