Compare commits
7 Commits
07024cef33
...
3af744c24d
| Author | SHA1 | Date | |
|---|---|---|---|
|
3af744c24d
|
|||
|
a140245c05
|
|||
|
36c06874fa
|
|||
|
dd1f271674
|
|||
|
a2e525c2da
|
|||
|
6cb81d452d
|
|||
|
675c8a5b12
|
28
src/async.ts
28
src/async.ts
@@ -4,6 +4,7 @@ import { createQueue } from "./queue.js";
|
|||||||
import { selectionSorter } from "./sorting.js";
|
import { selectionSorter } from "./sorting.js";
|
||||||
import { createAsyncEqualitySet } from "./equality-set.js";
|
import { createAsyncEqualitySet } from "./equality-set.js";
|
||||||
import { createAsyncEqualityMap } from "./equality-map.js";
|
import { createAsyncEqualityMap } from "./equality-map.js";
|
||||||
|
import { Collector } from "./collector.js";
|
||||||
|
|
||||||
//#region types
|
//#region types
|
||||||
|
|
||||||
@@ -134,6 +135,8 @@ export interface AsyncEnumerable<TElement> extends AsyncIterable<TElement> {
|
|||||||
toMap<TKey, TValue>(keySelector: MaybeAsyncConverter<TElement, TKey>, valueSelector: MaybeAsyncConverter<TElement, TValue>): Promise<Map<TKey, TValue>>;
|
toMap<TKey, TValue>(keySelector: MaybeAsyncConverter<TElement, TKey>, valueSelector: MaybeAsyncConverter<TElement, TValue>): Promise<Map<TKey, TValue>>;
|
||||||
toSet(): Promise<Set<TElement>>;
|
toSet(): Promise<Set<TElement>>;
|
||||||
toObject<TValue>(keySelector: MaybeAsyncConverter<TElement, PropertyKey>, valueSelector: MaybeAsyncConverter<TElement, TValue>): Promise<Record<PropertyKey, TValue>>;
|
toObject<TValue>(keySelector: MaybeAsyncConverter<TElement, PropertyKey>, valueSelector: MaybeAsyncConverter<TElement, TValue>): Promise<Record<PropertyKey, TValue>>;
|
||||||
|
|
||||||
|
collect<TResult>(collector: Collector<TElement, any, TResult>): Promise<TResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupedAsyncEnumerable<TKey, TElement> extends AsyncEnumerable<TElement> {
|
export interface GroupedAsyncEnumerable<TKey, TElement> extends AsyncEnumerable<TElement> {
|
||||||
@@ -378,8 +381,7 @@ export abstract class BaseAsyncEnumerable<TElement> implements AsyncEnumerable<T
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const arr = new Array<AsyncEnumerable<TElement>>();
|
const arr: AsyncEnumerable<TElement>[] = [this];
|
||||||
arr.push(this);
|
|
||||||
|
|
||||||
for (const iterable of iterables) {
|
for (const iterable of iterables) {
|
||||||
arr.push(wrap(iterable));
|
arr.push(wrap(iterable));
|
||||||
@@ -855,7 +857,7 @@ export abstract class BaseAsyncEnumerable<TElement> implements AsyncEnumerable<T
|
|||||||
}
|
}
|
||||||
|
|
||||||
async toArray() {
|
async toArray() {
|
||||||
const array = new Array<TElement>();
|
const array: TElement[] = [];
|
||||||
|
|
||||||
for await (const element of this) {
|
for await (const element of this) {
|
||||||
array.push(element);
|
array.push(element);
|
||||||
@@ -899,6 +901,16 @@ export abstract class BaseAsyncEnumerable<TElement> implements AsyncEnumerable<T
|
|||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async collect<TResult>(collector: Collector<TElement, any, TResult>) {
|
||||||
|
const acc = collector.initialize();
|
||||||
|
|
||||||
|
for await (const e of this) {
|
||||||
|
collector.accumulate(acc, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return collector.finalize(acc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroupedAsyncEnumerableImpl<TElement, TKey> extends BaseAsyncEnumerable<TElement> implements GroupedAsyncEnumerable<TKey, TElement> {
|
class GroupedAsyncEnumerableImpl<TElement, TKey> extends BaseAsyncEnumerable<TElement> implements GroupedAsyncEnumerable<TKey, TElement> {
|
||||||
@@ -963,7 +975,7 @@ abstract class BaseOrderedAsyncEnumerable<TElement> extends BaseAsyncEnumerable<
|
|||||||
}
|
}
|
||||||
|
|
||||||
override async *iterator() {
|
override async *iterator() {
|
||||||
const arr = new Array<TElement>();
|
const arr: TElement[] = [];
|
||||||
|
|
||||||
for await (const obj of this.#enumerable) {
|
for await (const obj of this.#enumerable) {
|
||||||
arr.push(obj);
|
arr.push(obj);
|
||||||
@@ -1868,7 +1880,7 @@ class ReversedAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override async *iterator() {
|
override async *iterator() {
|
||||||
const buffer = new Array<T>();
|
const buffer: T[] = [];
|
||||||
|
|
||||||
for await (const obj of this.#enumerable) {
|
for await (const obj of this.#enumerable) {
|
||||||
buffer.push(obj);
|
buffer.push(obj);
|
||||||
@@ -1932,14 +1944,14 @@ class ChunkedAsyncEnumerable<T> extends BaseAsyncEnumerable<T[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override async *iterator() {
|
override async *iterator() {
|
||||||
let chunk = new Array<T>();
|
let chunk: T[] = [];
|
||||||
|
|
||||||
for await (const obj of this.#enumerable) {
|
for await (const obj of this.#enumerable) {
|
||||||
chunk.push(obj);
|
chunk.push(obj);
|
||||||
|
|
||||||
if (chunk.length === this.#size) {
|
if (chunk.length === this.#size) {
|
||||||
yield chunk;
|
yield chunk;
|
||||||
chunk = new Array<T>();
|
chunk = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2009,7 +2021,7 @@ class GroupJoinAsyncEnumerable<TOuter, TInner, TKey, TResult> extends BaseAsyncE
|
|||||||
override async *iterator() {
|
override async *iterator() {
|
||||||
for await (const firstObj of this.#first) {
|
for await (const firstObj of this.#first) {
|
||||||
const firstKey = await this.#firstKeySelector(firstObj);
|
const firstKey = await this.#firstKeySelector(firstObj);
|
||||||
const secondObjs = new Array<TInner>();
|
const secondObjs: TInner[] = [];
|
||||||
|
|
||||||
for await (const secondObj of this.#second) {
|
for await (const secondObj of this.#second) {
|
||||||
const secondKey = await this.#secondKeySelector(secondObj);
|
const secondKey = await this.#secondKeySelector(secondObj);
|
||||||
|
|||||||
276
src/bitarray.ts
276
src/bitarray.ts
@@ -1,7 +1,34 @@
|
|||||||
import { join } from "./collector.js";
|
import { join } from "./collector.js";
|
||||||
import { arrayLike, sequence } from "./sync.js";
|
import { Enumerable, arrayLike, sequence } from "./sync.js";
|
||||||
import { asArray, isDefined } from "./utils.js";
|
import { asArray, isDefined } from "./utils.js";
|
||||||
|
|
||||||
|
export interface BitArray extends Iterable<boolean> {
|
||||||
|
readonly length: number;
|
||||||
|
|
||||||
|
isFull(): boolean;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
|
||||||
|
get(index: number): boolean;
|
||||||
|
set(index: number, value: boolean): void;
|
||||||
|
fill(value: boolean): void;
|
||||||
|
|
||||||
|
and(other: BitArray): BitArray;
|
||||||
|
or(other: BitArray): BitArray;
|
||||||
|
xor(other: BitArray): BitArray;
|
||||||
|
not(): BitArray;
|
||||||
|
|
||||||
|
contains(other: BitArray): boolean;
|
||||||
|
intersects(other: BitArray): boolean;
|
||||||
|
|
||||||
|
slice(offset: number, length: number): BitArray;
|
||||||
|
copy(): BitArray;
|
||||||
|
toArray(): boolean[];
|
||||||
|
|
||||||
|
equals(other: BitArray): boolean;
|
||||||
|
|
||||||
|
toString(): string;
|
||||||
|
}
|
||||||
|
|
||||||
const BYTE_SIZE = Uint8Array.BYTES_PER_ELEMENT * 8;
|
const BYTE_SIZE = Uint8Array.BYTES_PER_ELEMENT * 8;
|
||||||
const FULL_BYTE = getMask(BYTE_SIZE);
|
const FULL_BYTE = getMask(BYTE_SIZE);
|
||||||
|
|
||||||
@@ -54,7 +81,29 @@ function* getBytes(bits: Iterable<boolean>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BitArray implements Iterable<boolean> {
|
export namespace BitArray {
|
||||||
|
export function create(length: number): BitArray {
|
||||||
|
return new BitArrayImpl(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function from(bits: Iterable<boolean>): BitArray {
|
||||||
|
const arr = asArray(bits);
|
||||||
|
const result = create(arr.length);
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
for (const bit of arr) {
|
||||||
|
result.set(i++, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function of(...bits: boolean[]): BitArray {
|
||||||
|
return from(bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BitArrayImpl implements BitArray {
|
||||||
readonly #length: number;
|
readonly #length: number;
|
||||||
readonly #bits: Uint8Array;
|
readonly #bits: Uint8Array;
|
||||||
readonly #wholeBytes: number;
|
readonly #wholeBytes: number;
|
||||||
@@ -72,22 +121,6 @@ export class BitArray implements Iterable<boolean> {
|
|||||||
this.#remainingBitsMask = getMask(remainingBits);
|
this.#remainingBitsMask = getMask(remainingBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static from(bits: Iterable<boolean>) {
|
|
||||||
const arr = asArray(bits);
|
|
||||||
const result = new this(arr.length);
|
|
||||||
|
|
||||||
let i = 0;
|
|
||||||
for (const bit of arr) {
|
|
||||||
result.set(i++, bit);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static of(...bits: boolean[]) {
|
|
||||||
return this.from(bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
*[Symbol.iterator]() {
|
*[Symbol.iterator]() {
|
||||||
for (let i = 0; i < this.#wholeBytes; i++) {
|
for (let i = 0; i < this.#wholeBytes; i++) {
|
||||||
yield* yieldBits(this.#bits[i], BYTE_SIZE);
|
yield* yieldBits(this.#bits[i], BYTE_SIZE);
|
||||||
@@ -149,8 +182,15 @@ export class BitArray implements Iterable<boolean> {
|
|||||||
public and(other: BitArray) {
|
public and(other: BitArray) {
|
||||||
this.#ensureSameSize(other);
|
this.#ensureSameSize(other);
|
||||||
|
|
||||||
for (let i = 0; i < this.#length; i++) {
|
if (other instanceof BitArrayImpl) {
|
||||||
this.#bits[i] &= other.#bits[i];
|
for (let i = 0; i < this.#length; i++) {
|
||||||
|
this.#bits[i] &= other.#bits[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let i = 0;
|
||||||
|
for (const byte of getBytes(other)) {
|
||||||
|
this.#bits[i++] &= byte;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@@ -159,8 +199,15 @@ export class BitArray implements Iterable<boolean> {
|
|||||||
public or(other: BitArray) {
|
public or(other: BitArray) {
|
||||||
this.#ensureSameSize(other);
|
this.#ensureSameSize(other);
|
||||||
|
|
||||||
for (let i = 0; i < this.#length; i++) {
|
if (other instanceof BitArrayImpl) {
|
||||||
this.#bits[i] |= other.#bits[i];
|
for (let i = 0; i < this.#length; i++) {
|
||||||
|
this.#bits[i] |= other.#bits[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let i = 0;
|
||||||
|
for (const byte of getBytes(other)) {
|
||||||
|
this.#bits[i++] |= byte;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@@ -169,8 +216,15 @@ export class BitArray implements Iterable<boolean> {
|
|||||||
public xor(other: BitArray) {
|
public xor(other: BitArray) {
|
||||||
this.#ensureSameSize(other);
|
this.#ensureSameSize(other);
|
||||||
|
|
||||||
for (let i = 0; i < this.#length; i++) {
|
if (other instanceof BitArrayImpl) {
|
||||||
this.#bits[i] ^= other.#bits[i];
|
for (let i = 0; i < this.#length; i++) {
|
||||||
|
this.#bits[i] ^= other.#bits[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let i = 0;
|
||||||
|
for (const byte of getBytes(other)) {
|
||||||
|
this.#bits[i++] ^= byte;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@@ -188,30 +242,28 @@ export class BitArray implements Iterable<boolean> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public andNot(other: BitArray) {
|
|
||||||
this.#ensureSameSize(other);
|
|
||||||
|
|
||||||
for (let i = 0; i < this.#length; i++) {
|
|
||||||
this.#bits[i] &= ~other.#bits[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public contains(other: BitArray) {
|
public contains(other: BitArray) {
|
||||||
this.#ensureSameSize(other);
|
this.#ensureSameSize(other);
|
||||||
|
|
||||||
return arrayLike(this.#bits).zip(arrayLike(other.#bits)).all(([a, b]) => (a & b) === b);
|
return other instanceof BitArrayImpl ?
|
||||||
|
arrayLike(this.#bits).zip(arrayLike(other.#bits)).all(([a, b]) => (a & b) === b) :
|
||||||
|
sequence(this).zip(sequence(other)).where(([, b]) => b).all(([a, b]) => a && b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public intersects(other: BitArray) {
|
public intersects(other: BitArray) {
|
||||||
this.#ensureSameSize(other);
|
this.#ensureSameSize(other);
|
||||||
|
|
||||||
return arrayLike(this.#bits).zip(arrayLike(other.#bits)).any(([a, b]) => (a & b) !== 0);
|
return other instanceof BitArrayImpl ?
|
||||||
|
arrayLike(this.#bits).zip(arrayLike(other.#bits)).any(([a, b]) => (a & b) !== 0) :
|
||||||
|
sequence(this).zip(sequence(other)).any(([a, b]) => a && b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public slice(offset: number, length: number) {
|
||||||
|
return new BitArraySlice(this, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public copy() {
|
public copy() {
|
||||||
const copy = new BitArray(this.#length);
|
const copy = new BitArrayImpl(this.#length);
|
||||||
copy.#bits.set(this.#bits);
|
copy.#bits.set(this.#bits);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
@@ -221,7 +273,155 @@ export class BitArray implements Iterable<boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public equals(other: BitArray) {
|
public equals(other: BitArray) {
|
||||||
return other === this || isDefined(other) && arrayLike(this.#bits).equals(arrayLike(other.#bits));
|
return other === this || isDefined(other) && (other instanceof BitArrayImpl ? arrayLike(this.#bits).equals(arrayLike(other.#bits)) : sequence(this).equals(sequence(other)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public toString() {
|
||||||
|
return sequence(this).select(bit => bit ? '1' : '0').collect(join());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BitArraySlice implements BitArray {
|
||||||
|
readonly #parent: BitArray;
|
||||||
|
readonly #offset: number;
|
||||||
|
readonly #length: number;
|
||||||
|
|
||||||
|
public constructor(parent: BitArray, offset: number, length: number) {
|
||||||
|
this.#parent = parent;
|
||||||
|
this.#offset = offset;
|
||||||
|
this.#length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
*[Symbol.iterator]() {
|
||||||
|
for (let i = 0; i < this.#length; i++) {
|
||||||
|
yield this.#parent.get(i + this.#offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ensureValidIndex(index: number) {
|
||||||
|
if (index < 0 || index >= this.#length) {
|
||||||
|
throw new RangeError("The index is outside the BitArray range.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ensureSameSize(other: BitArray) {
|
||||||
|
if (this.#length !== other.length) {
|
||||||
|
throw new TypeError("The BitArrays do not have the same length.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get length() {
|
||||||
|
return this.#length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isFull() {
|
||||||
|
for (const bit of this) {
|
||||||
|
if (!bit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isEmpty() {
|
||||||
|
for (const bit of this) {
|
||||||
|
if (bit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(index: number) {
|
||||||
|
this.#ensureValidIndex(index);
|
||||||
|
|
||||||
|
return this.#parent.get(index + this.#offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public set(index: number, value: boolean) {
|
||||||
|
this.#ensureValidIndex(index);
|
||||||
|
|
||||||
|
this.#parent.set(index + this.#offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public fill(value: boolean) {
|
||||||
|
for (let i = 0; i < this.#length; i++) {
|
||||||
|
this.#parent.set(i + this.#offset, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public and(other: BitArray) {
|
||||||
|
this.#ensureSameSize(other);
|
||||||
|
|
||||||
|
for (let i = 0; i < this.#length; i++) {
|
||||||
|
this.set(i, this.get(i) && other.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public or(other: BitArray) {
|
||||||
|
this.#ensureSameSize(other);
|
||||||
|
|
||||||
|
for (let i = 0; i < this.#length; i++) {
|
||||||
|
this.set(i, this.get(i) || other.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public xor(other: BitArray) {
|
||||||
|
this.#ensureSameSize(other);
|
||||||
|
|
||||||
|
for (let i = 0; i < this.#length; i++) {
|
||||||
|
this.set(i, this.get(i) !== other.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public not() {
|
||||||
|
for (let i = 0; i < this.#length; i++) {
|
||||||
|
this.set(i, !this.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public contains(other: BitArray) {
|
||||||
|
this.#ensureSameSize(other);
|
||||||
|
|
||||||
|
return sequence(this).zip(sequence(other)).where(([, b]) => b).all(([a, b]) => a && b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public intersects(other: BitArray) {
|
||||||
|
this.#ensureSameSize(other);
|
||||||
|
|
||||||
|
return sequence(this).zip(sequence(other)).any(([a, b]) => a && b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public slice(offset: number, length: number) {
|
||||||
|
return new BitArraySlice(this.#parent, offset + this.#offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public copy() {
|
||||||
|
const copy = new BitArrayImpl(this.#length);
|
||||||
|
|
||||||
|
for (let i = 0; i < this.#length; i++) {
|
||||||
|
copy.set(i, this.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public toArray() {
|
||||||
|
return sequence(this).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public equals(other: BitArray) {
|
||||||
|
return other === this || isDefined(other) && sequence(this).equals(sequence(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
public toString() {
|
public toString() {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ function mergeOptions<T>(first: RandomOptions<T> | undefined, second: RandomOpti
|
|||||||
}
|
}
|
||||||
|
|
||||||
function withDefaultOptions<T>(options: RandomOptions<T> | undefined): Required<RandomOptions<T>> {
|
function withDefaultOptions<T>(options: RandomOptions<T> | undefined): Required<RandomOptions<T>> {
|
||||||
if (!options) {
|
if (!options || options === defaultOptions) {
|
||||||
return defaultOptions;
|
return defaultOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,8 +52,8 @@ function withDefaultOptions<T>(options: RandomOptions<T> | undefined): Required<
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRandomElement<T>(sequence: Iterable<T>, options?: RandomOptions<T>) {
|
function _getRandomElement<T>(sequence: Iterable<T>, options: Required<RandomOptions<T>>) {
|
||||||
const { predicate, weight, random } = withDefaultOptions(options);
|
const { predicate, weight, random } = options;
|
||||||
|
|
||||||
let result: T | undefined = undefined;
|
let result: T | undefined = undefined;
|
||||||
let resultIndex = -1;
|
let resultIndex = -1;
|
||||||
@@ -82,14 +82,18 @@ export function getRandomElement<T>(sequence: Iterable<T>, options?: RandomOptio
|
|||||||
return { element: result, index: resultIndex };
|
return { element: result, index: resultIndex };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRandomElement<T>(sequence: Iterable<T>, options?: RandomOptions<T>) {
|
||||||
|
return _getRandomElement(sequence, withDefaultOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
export class RandomPicker<T> {
|
export class RandomPicker<T> {
|
||||||
readonly #elements: Iterable<T>;
|
readonly #elements: Iterable<T>;
|
||||||
readonly #flags: BitArray;
|
readonly #flags: BitArray;
|
||||||
readonly #options: RandomOptions<T>;
|
readonly #options: Required<RandomOptions<T>>;
|
||||||
|
|
||||||
public constructor(elements: T[], options?: RandomOptions<T>) {
|
public constructor(elements: T[], options?: RandomOptions<T>) {
|
||||||
this.#elements = elements;
|
this.#elements = elements;
|
||||||
this.#flags = new BitArray(elements.length);
|
this.#flags = BitArray.create(elements.length);
|
||||||
this.#options = withDefaultOptions(mergeOptions({ predicate: i => this.#flags.get(i) }, options));
|
this.#options = withDefaultOptions(mergeOptions({ predicate: i => this.#flags.get(i) }, options));
|
||||||
|
|
||||||
this.reset();
|
this.reset();
|
||||||
@@ -112,7 +116,7 @@ export class RandomPicker<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public next() {
|
public next() {
|
||||||
const result = getRandomElement(this.#elements, this.#options);
|
const result = _getRandomElement(this.#elements, this.#options);
|
||||||
|
|
||||||
if (result.index < 0) {
|
if (result.index < 0) {
|
||||||
this.reset();
|
this.reset();
|
||||||
|
|||||||
13
src/sync.ts
13
src/sync.ts
@@ -396,8 +396,7 @@ export abstract class BaseEnumerable<TElement> extends EnumerableMarker implemen
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const arr = new Array<Enumerable<TElement>>();
|
const arr: Enumerable<TElement>[] = [this];
|
||||||
arr.push(this);
|
|
||||||
|
|
||||||
for (const iterable of iterables) {
|
for (const iterable of iterables) {
|
||||||
arr.push(wrap(iterable));
|
arr.push(wrap(iterable));
|
||||||
@@ -1297,7 +1296,7 @@ abstract class BaseOrderedEnumerable<TElement> extends BaseEnumerable<TElement>
|
|||||||
}
|
}
|
||||||
|
|
||||||
override *iterator() {
|
override *iterator() {
|
||||||
const arr = new Array<TElement>();
|
const arr: TElement[] = [];
|
||||||
|
|
||||||
for (const obj of this.#enumerable) {
|
for (const obj of this.#enumerable) {
|
||||||
arr.push(obj);
|
arr.push(obj);
|
||||||
@@ -2450,7 +2449,7 @@ class ReversedEnumerable<T> extends BaseEnumerable<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override *iterator() {
|
override *iterator() {
|
||||||
const buffer = new Array<T>();
|
const buffer: T[] = [];
|
||||||
|
|
||||||
for (const obj of this.#enumerable) {
|
for (const obj of this.#enumerable) {
|
||||||
buffer.push(obj);
|
buffer.push(obj);
|
||||||
@@ -2522,14 +2521,14 @@ class ChunkedEnumerable<T> extends BaseEnumerable<T[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override *iterator() {
|
override *iterator() {
|
||||||
let chunk = new Array<T>();
|
let chunk: T[] = [];
|
||||||
|
|
||||||
for (const obj of this.#enumerable) {
|
for (const obj of this.#enumerable) {
|
||||||
chunk.push(obj);
|
chunk.push(obj);
|
||||||
|
|
||||||
if (chunk.length === this.#size) {
|
if (chunk.length === this.#size) {
|
||||||
yield chunk;
|
yield chunk;
|
||||||
chunk = new Array<T>();
|
chunk = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2615,7 +2614,7 @@ class GroupJoinEnumerable<TOuter, TInner, TKey, TResult> extends BaseEnumerable<
|
|||||||
override *iterator() {
|
override *iterator() {
|
||||||
for (const firstObj of this.#first) {
|
for (const firstObj of this.#first) {
|
||||||
const firstKey = this.#firstKeySelector(firstObj);
|
const firstKey = this.#firstKeySelector(firstObj);
|
||||||
const secondObjs = new Array<TInner>();
|
const secondObjs: TInner[] = [];
|
||||||
|
|
||||||
for (const secondObj of this.#second) {
|
for (const secondObj of this.#second) {
|
||||||
const secondKey = this.#secondKeySelector(secondObj);
|
const secondKey = this.#secondKeySelector(secondObj);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function strictEquals<T>(a: T, b: T) {
|
|||||||
return a === b;
|
return a === b;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isEquals<T>(a: T, b: T) {
|
export function referenceEquals<T>(a: T, b: T) {
|
||||||
return Object.is(a, b);
|
return Object.is(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,11 +68,11 @@ export function combineAsyncComparers<T>(first: MaybeAsyncComparer<T>, second: M
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function reverseComparer<T>(comparer: Comparer<T>): Comparer<T> {
|
export function reverseComparer<T>(comparer: Comparer<T>): Comparer<T> {
|
||||||
return (a: T, b: T) => comparer(b, a);
|
return (a, b) => comparer(b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function reverseAsyncComparer<T>(comparer: MaybeAsyncComparer<T>): AsyncComparer<T> {
|
export function reverseAsyncComparer<T>(comparer: MaybeAsyncComparer<T>): AsyncComparer<T> {
|
||||||
return async (a: T, b: T) => await comparer(b, a);
|
return async (a, b) => await comparer(b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* asGenerator<T>(iterator: Iterator<T>) {
|
export function* asGenerator<T>(iterator: Iterator<T>) {
|
||||||
@@ -116,5 +116,5 @@ class WrappedIterator<T> implements Iterable<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function wrapAsIterable<T>(iterator: Iterator<T>): Iterable<T> {
|
export function wrapAsIterable<T>(iterator: Iterator<T>): Iterable<T> {
|
||||||
return new WrappedIterator(iterator);
|
return isIterable<T>(iterator) ? iterator : new WrappedIterator(iterator);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user