forked from engineering/crv2
155 lines
3.7 KiB
TypeScript
155 lines
3.7 KiB
TypeScript
/**
|
|
* Hold a bunch of something
|
|
*/
|
|
export default class Collection<V> extends Map<string, V> {
|
|
baseObject: (new (...args: any[]) => V) | undefined;
|
|
|
|
/**
|
|
* Creates an instance of Collection
|
|
*/
|
|
constructor(iterable: Iterable<[string, V]> | object | null = null) {
|
|
if (iterable && iterable instanceof Array) {
|
|
super(iterable);
|
|
} else if (iterable && iterable instanceof Object) {
|
|
super(Object.entries(iterable));
|
|
} else {
|
|
super();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Map to array
|
|
* ```js
|
|
* [value, value, value]
|
|
* ```
|
|
*/
|
|
toArray(): V[] {
|
|
return [...this.values()];
|
|
}
|
|
|
|
/**
|
|
* Map to object
|
|
* ```js
|
|
* { key: value, key: value, key: value }
|
|
* ```
|
|
*/
|
|
toObject(): { [key: string]: V } {
|
|
const obj: { [key: string]: V } = {};
|
|
for (const [key, value] of this.entries()) {
|
|
obj[key] = value;
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
/**
|
|
* Add an object
|
|
*
|
|
* If baseObject, add only if instance of baseObject
|
|
*
|
|
* If no baseObject, add
|
|
* @param key The key of the object
|
|
* @param value The object data
|
|
* @param replace Whether to replace an existing object with the same key
|
|
* @return The existing or newly created object
|
|
*/
|
|
add(key: string, value: V, replace: boolean = false): V | undefined | null {
|
|
if (this.has(key) && !replace) {
|
|
return this.get(key);
|
|
}
|
|
if (this.baseObject && !(value instanceof this.baseObject)) return null;
|
|
|
|
this.set(key, value);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Return the first object to make the function evaluate true
|
|
* @param func A function that takes an object and returns something
|
|
* @return The first matching object, or `null` if no match
|
|
*/
|
|
find(func: Function): V | null {
|
|
for (const item of this.values()) {
|
|
if (func(item)) return item;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Return an array with the results of applying the given function to each element
|
|
* @param callbackfn A function that takes an object and returns something
|
|
*/
|
|
map<U>(callbackfn: (value?: V, index?: number, array?: V[]) => U): U[] {
|
|
const arr = [];
|
|
for (const item of this.values()) {
|
|
arr.push(callbackfn(item));
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
/**
|
|
* Return all the objects that make the function evaluate true
|
|
* @param func A function that takes an object and returns true if it matches
|
|
*/
|
|
filter(func: (value: V) => boolean): V[] {
|
|
const arr = [];
|
|
for (const item of this.values()) {
|
|
if (func(item)) {
|
|
arr.push(item);
|
|
}
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
/**
|
|
* Test if at least one element passes the test implemented by the provided function. Returns true if yes, or false if not.
|
|
* @param func A function that takes an object and returns true if it matches
|
|
*/
|
|
some(func: (value: V) => boolean) {
|
|
for (const item of this.values()) {
|
|
if (func(item)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Update an object
|
|
* @param key The key of the object
|
|
* @param value The updated object data
|
|
*/
|
|
update(key: string, value: V) {
|
|
return this.add(key, value, true);
|
|
}
|
|
|
|
/**
|
|
* Remove an object
|
|
* @param key The key of the object
|
|
* @returns The removed object, or `null` if nothing was removed
|
|
*/
|
|
remove(key: string): V | null {
|
|
const item = this.get(key);
|
|
if (!item) {
|
|
return null;
|
|
}
|
|
this.delete(key);
|
|
return item;
|
|
}
|
|
|
|
/**
|
|
* Get a random object from the Collection
|
|
* @returns The random object or `null` if empty
|
|
*/
|
|
random(): V | null {
|
|
if (!this.size) {
|
|
return null;
|
|
}
|
|
return Array.from(this.values())[Math.floor(Math.random() * this.size)];
|
|
}
|
|
|
|
toString() {
|
|
// @ts-ignore
|
|
return `[Collection<${this.baseObject.name}>]`;
|
|
}
|
|
}
|