import { toList, toArray, map, filter, delay } from "./Seq.ts"; import { HashSet } from "./MutableSet.ts"; import { MutableArray, defaultOf, IDisposable, disposeSafe, IEnumerator, getEnumerator, IMap, IEqualityComparer, ISet } from "./Util.ts"; import { addToDict, getItemFromDict, tryGetValue, addToSet } from "./MapUtil.ts"; import { Dictionary } from "./MutableMap.ts"; import { int32 } from "./Int32.ts"; import { FSharpRef } from "./Types.ts"; import { FSharpList } from "./List.ts"; export function distinct(xs: Iterable, comparer: IEqualityComparer): Iterable { return delay((): Iterable => { const hashSet: ISet = new HashSet([], comparer); return filter((x: T): boolean => addToSet(x, hashSet), xs); }); } export function distinctBy(projection: ((arg0: T) => Key), xs: Iterable, comparer: IEqualityComparer): Iterable { return delay((): Iterable => { const hashSet: ISet = new HashSet([], comparer); return filter((x: T): boolean => addToSet(projection(x), hashSet), xs); }); } export function except(itemsToExclude: Iterable, xs: Iterable, comparer: IEqualityComparer): Iterable { return delay((): Iterable => { const hashSet: ISet = new HashSet(itemsToExclude, comparer); return filter((x: T): boolean => addToSet(x, hashSet), xs); }); } export function countBy(projection: ((arg0: T) => Key), xs: Iterable, comparer: IEqualityComparer): Iterable<[Key, int32]> { return delay<[Key, int32]>((): Iterable<[Key, int32]> => { const dict: IMap = new Dictionary([], comparer); const keys: Key[] = []; const enumerator: IEnumerator = getEnumerator(xs); try { while (enumerator["System.Collections.IEnumerator.MoveNext"]()) { const key: Key = projection(enumerator["System.Collections.Generic.IEnumerator`1.get_Current"]()); let matchValue: [boolean, int32]; let outArg = 0; matchValue = ([tryGetValue(dict, key, new FSharpRef((): int32 => (outArg | 0), (v: int32): void => { outArg = (v | 0); })), outArg] as [boolean, int32]); if (matchValue[0]) { dict.set(key, matchValue[1] + 1); } else { dict.set(key, 1); void (keys.push(key)); } } } finally { disposeSafe(enumerator as IDisposable); } return map((key_1: Key): [Key, int32] => ([key_1, getItemFromDict(dict, key_1)] as [Key, int32]), keys); }); } export function groupBy(projection: ((arg0: T) => Key), xs: Iterable, comparer: IEqualityComparer): Iterable<[Key, Iterable]> { return delay<[Key, Iterable]>((): Iterable<[Key, Iterable]> => { const dict: IMap = new Dictionary([], comparer); const keys: Key[] = []; const enumerator: IEnumerator = getEnumerator(xs); try { while (enumerator["System.Collections.IEnumerator.MoveNext"]()) { const x: T = enumerator["System.Collections.Generic.IEnumerator`1.get_Current"](); const key: Key = projection(x); let matchValue: [boolean, T[]]; let outArg: T[] = defaultOf(); matchValue = ([tryGetValue(dict, key, new FSharpRef((): T[] => outArg, (v: T[]): void => { outArg = v; })), outArg] as [boolean, T[]]); if (matchValue[0]) { void (matchValue[1].push(x)); } else { addToDict(dict, key, [x]); void (keys.push(key)); } } } finally { disposeSafe(enumerator as IDisposable); } return map]>((key_1: Key): [Key, Iterable] => ([key_1, getItemFromDict(dict, key_1)] as [Key, Iterable]), keys); }); } export function Array_distinct(xs: MutableArray, comparer: IEqualityComparer): MutableArray { return toArray(distinct(xs, comparer)); } export function Array_distinctBy(projection: ((arg0: T) => Key), xs: MutableArray, comparer: IEqualityComparer): MutableArray { return toArray(distinctBy(projection, xs, comparer)); } export function Array_except(itemsToExclude: Iterable, xs: MutableArray, comparer: IEqualityComparer): MutableArray { return toArray(except(itemsToExclude, xs, comparer)); } export function Array_countBy(projection: ((arg0: T) => Key), xs: MutableArray, comparer: IEqualityComparer): MutableArray<[Key, int32]> { return toArray<[Key, int32]>(countBy(projection, xs, comparer)); } export function Array_groupBy(projection: ((arg0: T) => Key), xs: MutableArray, comparer: IEqualityComparer): MutableArray<[Key, MutableArray]> { return toArray<[Key, MutableArray]>(map<[Key, Iterable], [Key, MutableArray]>((tupledArg: [Key, Iterable]): [Key, MutableArray] => ([tupledArg[0], toArray(tupledArg[1])] as [Key, MutableArray]), groupBy(projection, xs, comparer))); } export function List_distinct(xs: FSharpList, comparer: IEqualityComparer): FSharpList { return toList(distinct(xs, comparer)); } export function List_distinctBy(projection: ((arg0: T) => Key), xs: FSharpList, comparer: IEqualityComparer): FSharpList { return toList(distinctBy(projection, xs, comparer)); } export function List_except(itemsToExclude: Iterable, xs: FSharpList, comparer: IEqualityComparer): FSharpList { return toList(except(itemsToExclude, xs, comparer)); } export function List_countBy(projection: ((arg0: T) => Key), xs: FSharpList, comparer: IEqualityComparer): FSharpList<[Key, int32]> { return toList<[Key, int32]>(countBy(projection, xs, comparer)); } export function List_groupBy(projection: ((arg0: T) => Key), xs: FSharpList, comparer: IEqualityComparer): FSharpList<[Key, FSharpList]> { return toList<[Key, FSharpList]>(map<[Key, Iterable], [Key, FSharpList]>((tupledArg: [Key, Iterable]): [Key, FSharpList] => ([tupledArg[0], toList(tupledArg[1])] as [Key, FSharpList]), groupBy(projection, xs, comparer))); }