Last active
October 2, 2024 13:45
-
-
Save vitaly-t/2c868874738cc966df776f383e5e0247 to your computer and use it in GitHub Desktop.
Logically concatenates arrays
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Iterable arrays chain, extended for "getLength" and "at" accessor. | |
| */ | |
| export interface IArraysChain<T> extends RelativeIndexable<T>, Iterable<T> { | |
| /** | |
| * Calculates total length of all input arrays combined. | |
| */ | |
| getLength(): number; | |
| } | |
| export function chainArrays(): IArraysChain<unknown>; | |
| export function chainArrays<A>(a: ArrayLike<A>): IArraysChain<A>; | |
| export function chainArrays<A, B>(a: ArrayLike<A>, b: ArrayLike<B>): IArraysChain<A | B>; | |
| export function chainArrays<A, B, C>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>): IArraysChain<A | B | C>; | |
| export function chainArrays<A, B, C, D>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>): IArraysChain<A | B | C | D>; | |
| export function chainArrays<A, B, C, D, E>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>): IArraysChain<A | B | C | D | E>; | |
| export function chainArrays<A, B, C, D, E, F>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>, f: ArrayLike<F>): IArraysChain<A | B | C | D | E | F>; | |
| export function chainArrays<A, B, C, D, E, F, G>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>, f: ArrayLike<F>, g: ArrayLike<G>): IArraysChain<A | B | C | D | E | F | G>; | |
| export function chainArrays<A, B, C, D, E, F, G, H>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>, f: ArrayLike<F>, g: ArrayLike<G>, h: ArrayLike<H>): IArraysChain<A | B | C | D | E | F | G | H>; | |
| export function chainArrays<A, B, C, D, E, F, G, H, I>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>, f: ArrayLike<F>, g: ArrayLike<G>, h: ArrayLike<H>, i: ArrayLike<I>): IArraysChain<A | B | C | D | E | F | G | H | I>; | |
| export function chainArrays<A, B, C, D, E, F, G, H, I, J>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>, f: ArrayLike<F>, g: ArrayLike<G>, h: ArrayLike<H>, i: ArrayLike<I>, j: ArrayLike<J>): IArraysChain<A | B | C | D | E | F | G | H | I | J>; | |
| /** | |
| * Logically concatenates arrays (chains them), into an iterable. | |
| */ | |
| export function chainArrays<T>(...arr: Array<ArrayLike<T>>): IArraysChain<T> { | |
| return { | |
| getLength() { | |
| return arr.reduce((a, c) => a + c.length, 0); | |
| }, | |
| at(i: number): T | undefined { | |
| for (let j = 0; j < arr.length; j++) { | |
| if (i < arr[j].length) { | |
| return arr[j][i]; | |
| } | |
| i -= arr[j].length; | |
| } | |
| }, | |
| [Symbol.iterator](): Iterator<T> { | |
| let i = 0, k = -1, a: ArrayLike<T> = []; | |
| return { | |
| next(): IteratorResult<T> { | |
| while (i === a.length) { | |
| if (++k === arr.length) { | |
| return {done: true, value: undefined}; | |
| } | |
| a = arr[k]; | |
| i = 0; | |
| } | |
| return {done: false, value: a[i++]}; | |
| } | |
| }; | |
| } | |
| } | |
| } | |
| export function chainArraysReverse(): IArraysChain<unknown>; | |
| export function chainArraysReverse<A>(a: ArrayLike<A>): IArraysChain<A>; | |
| export function chainArraysReverse<A, B>(a: ArrayLike<A>, b: ArrayLike<B>): IArraysChain<A | B>; | |
| export function chainArraysReverse<A, B, C>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>): IArraysChain<A | B | C>; | |
| export function chainArraysReverse<A, B, C, D>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>): IArraysChain<A | B | C | D>; | |
| export function chainArraysReverse<A, B, C, D, E>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>): IArraysChain<A | B | C | D | E>; | |
| export function chainArraysReverse<A, B, C, D, E, F>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>, f: ArrayLike<F>): IArraysChain<A | B | C | D | E | F>; | |
| export function chainArraysReverse<A, B, C, D, E, F, G>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>, f: ArrayLike<F>, g: ArrayLike<G>): IArraysChain<A | B | C | D | E | F | G>; | |
| export function chainArraysReverse<A, B, C, D, E, F, G, H>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>, f: ArrayLike<F>, g: ArrayLike<G>, h: ArrayLike<H>): IArraysChain<A | B | C | D | E | F | G | H>; | |
| export function chainArraysReverse<A, B, C, D, E, F, G, H, I>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>, f: ArrayLike<F>, g: ArrayLike<G>, h: ArrayLike<H>, i: ArrayLike<I>): IArraysChain<A | B | C | D | E | F | G | H | I>; | |
| export function chainArraysReverse<A, B, C, D, E, F, G, H, I, J>(a: ArrayLike<A>, b: ArrayLike<B>, c: ArrayLike<C>, d: ArrayLike<D>, e: ArrayLike<E>, f: ArrayLike<F>, g: ArrayLike<G>, h: ArrayLike<H>, i: ArrayLike<I>, j: ArrayLike<J>): IArraysChain<A | B | C | D | E | F | G | H | I | J>; | |
| /** | |
| * Logically concatenates arrays (chains them), into a reversed iterable. | |
| */ | |
| export function chainArraysReverse<T>(...arr: Array<ArrayLike<T>>): IArraysChain<T> { | |
| return { | |
| getLength() { | |
| return arr.reduce((a, c) => a + c.length, 0); | |
| }, | |
| at(i: number): T | undefined { | |
| for (let j = arr.length - 1; j >= 0; j--) { | |
| if (i < arr[j].length) { | |
| return arr[j][arr[j].length - (i + 1)]; | |
| } | |
| i -= arr[j].length; | |
| } | |
| }, | |
| [Symbol.iterator](): Iterator<T> { | |
| let i = -1, k = arr.length, a: ArrayLike<T>; | |
| return { | |
| next(): IteratorResult<T> { | |
| while (i < 0) { | |
| if (--k < 0) { | |
| return {done: true, value: undefined}; | |
| } | |
| a = arr[k]; | |
| i = a.length - 1; | |
| } | |
| return {done: false, value: a[i--]}; | |
| } | |
| }; | |
| } | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As there was no way to update "length" when a source array changes, without a super-slow proxy, I had to just replace
lengthwithgetLengthmethod.This way, this code will retain its maximum performance.