1
0
Files
sequence-js/src/equality-set/impl.ts

238 lines
4.2 KiB
TypeScript

import { asAsyncEqualityComparer } from "../equality-comparer/async.js";
import { asEqualityComparer } from "../equality-comparer/sync.js";
import { AsyncEqualityComparer, EqualityComparer, EqualityComparisonOrComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js";
import { MaybeAsyncIterable } from "../types.js";
import { AsyncEqualitySet, EqualitySet } from "./types.js";
export class NativeEqualitySet<T> implements EqualitySet<T> {
readonly #set = new Set<T>();
get size() {
return this.#set.size;
}
add(value: T) {
const exists = this.contains(value);
this.#set.add(value);
return !exists;
}
addAll(values: Iterable<T>) {
let result = 0;
for (const value of values) {
if (this.add(value)) {
result++;
}
}
return result;
}
contains(value: T) {
return this.#set.has(value);
}
remove(value: T) {
return this.#set.delete(value);
}
clear() {
this.#set.clear();
}
values() {
return this.#set.values();
}
[Symbol.iterator]() {
return this.#set[Symbol.iterator]();
}
}
export class CustomEqualitySet<T> implements EqualitySet<T> {
readonly #list: T[] = [];
readonly #equater: EqualityComparer<T>;
constructor(equater: EqualityComparisonOrComparer<T>) {
this.#equater = asEqualityComparer(equater);
}
get size() {
return this.#list.length;
}
add(value: T) {
if (this.contains(value)) {
return false;
}
this.#list.push(value);
return true;
}
addAll(values: Iterable<T>) {
let result = 0;
for (const value of values) {
if (this.add(value)) {
result++;
}
}
return result;
}
contains(value: T) {
for (const val of this.#list) {
if (this.#equater.equals(value, val)) {
return true;
}
}
return false;
}
remove(value: T) {
const length = this.#list.length;
for (let i = 0; i < length; i++) {
if (this.#equater.equals(value, this.#list[i])) {
this.#list.splice(i, 1);
return true;
}
}
return false;
}
clear() {
this.#list.length = 0;
}
values() {
return this.#list.values();
}
[Symbol.iterator]() {
return this.#list[Symbol.iterator]();
}
}
export class NativeAsyncEqualitySet<T> implements AsyncEqualitySet<T> {
readonly #set = new Set<T>();
get size() {
return this.#set.size;
}
async add(value: T) {
const exists = await this.contains(value);
this.#set.add(value);
return !exists;
}
async addAll(values: MaybeAsyncIterable<T>) {
let result = 0;
for await (const value of values) {
if (await this.add(value)) {
result++;
}
}
return result;
}
async contains(value: T) {
return this.#set.has(value);
}
async remove(value: T) {
return this.#set.delete(value);
}
clear() {
this.#set.clear();
}
values() {
return this.#set.values();
}
[Symbol.iterator]() {
return this.#set[Symbol.iterator]();
}
}
export class CustomAsyncEqualitySet<T> implements AsyncEqualitySet<T> {
readonly #list: T[] = [];
readonly #equater: AsyncEqualityComparer<T>;
constructor(equater: MaybeAsyncEqualityComparisonOrComparer<T>) {
this.#equater = asAsyncEqualityComparer(equater);
}
get size() {
return this.#list.length;
}
async add(value: T) {
if (await this.contains(value)) {
return false;
}
this.#list.push(value);
return true;
}
async addAll(values: MaybeAsyncIterable<T>) {
let result = 0;
for await (const value of values) {
if (await this.add(value)) {
result++;
}
}
return result;
}
async contains(value: T) {
for (const val of this.#list) {
if (await this.#equater.equals(value, val)) {
return true;
}
}
return false;
}
async remove(value: T) {
const length = this.#list.length;
for (let i = 0; i < length; i++) {
if (await this.#equater.equals(value, this.#list[i])) {
this.#list.splice(i, 1);
return true;
}
}
return false;
}
clear() {
this.#list.length = 0;
}
values() {
return this[Symbol.iterator]();
}
[Symbol.iterator]() {
return this.#list[Symbol.iterator]();
}
}