You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AdLike2048/assets/mx/tools/MembershipSet.ts

79 lines
2.4 KiB

3 weeks ago
/**
* 项目禁用原生 Set(小游戏运行时对部分 Set 用法不稳定)。
* 用 Map<K, true> 表示成员集合;迭代时 yield key(与 Set 一致,而非 Map 的 [key, value])。
*/
export type MembershipSet<K> = Map<K, true>;
export type ReadonlyMembershipSet<K> = ReadonlyMap<K, true>;
function bindMembershipIterator<K>(set: Map<K, true>): MembershipSet<K> {
(set as unknown as { [Symbol.iterator]: () => IterableIterator<K> })[Symbol.iterator] = () => set.keys();
return set;
}
export function createMembershipSet<K>(): MembershipSet<K> {
return bindMembershipIterator(new Map<K, true>());
}
export function membershipAdd<K>(set: MembershipSet<K>, key: K): MembershipSet<K> {
set.set(key, true);
return set;
}
export function membershipHas<K>(set: ReadonlyMembershipSet<K>, key: K): boolean {
return set.has(key);
}
export function membershipDelete<K>(set: MembershipSet<K>, key: K): boolean {
return set.delete(key);
}
export function membershipClear<K>(set: MembershipSet<K>): void {
set.clear();
}
export function membershipFromArray<K>(items: Iterable<K>): MembershipSet<K> {
const set = createMembershipSet<K>();
for (const item of items) {
set.set(item, true);
}
return set;
}
/**
* 将 Map 的 key 收成数组。
* 勿用 `[...map.keys()]` / `Array.from(map.keys())`:H5 构建可能编成 `concat(iterator)`,得到空对象。
*/
export function mapKeysToArray<K, V>(map: ReadonlyMap<K, V>): K[] {
const out: K[] = [];
map.forEach((_v, k) => {
out.push(k);
});
return out;
}
/**
* 将 Map 的 value 收成数组。
* 勿用 `[...map.values()]` / `Array.from(map.values())`。
*/
export function mapValuesToArray<K, V>(map: ReadonlyMap<K, V>): V[] {
const out: V[] = [];
map.forEach((v) => {
out.push(v);
});
return out;
}
/** 成员集合转数组(forEach 收 key,避免展开 Map 迭代器) */
export function membershipToArray<K>(set: ReadonlyMembershipSet<K>): K[] {
return mapKeysToArray(set);
}
export function membershipForEach<K>(set: ReadonlyMembershipSet<K>, fn: (key: K) => void): void {
set.forEach((_v, key) => fn(key));
}
/** 去重数组(替代 Array.from(new Set(...)) / [...new Set(...)]) */
export function membershipDedupeArray<K>(items: Iterable<K>): K[] {
return membershipToArray(membershipFromArray(items));
}