UNPKG

dotnetjs

Version:

.Net framework support in javascript

503 lines (434 loc) 20 kB
module DotnetJs.Linq { export function LinqStart<TSource>(source: Collections.IEnumerable<TSource>): LinqIntermediate<TSource, TSource> { return new LinqIntermediate<TSource, TSource>([source], DefaultDelegate.SelfReturn); } export class LinqIntermediate<TSource, TResult> implements Collections.IEnumerable<TResult> { protected toResult: (item: TSource, index: number) => TResult; protected sources: Collections.IEnumerable<TSource>[]; constructor(sources: Collections.IEnumerable<TSource>[], func: (item: TSource, index: number) => TResult) { this.sources = sources; this.toResult = func; } public GetEnumerator(): Collections.IEnumerator<TResult> { return new LinqEnumerator(this.sources, this.toResult); } public Aggregate<TAccumulate>(seed: TAccumulate, func: (acc: TAccumulate, item: TResult) => TAccumulate): TAccumulate { return Aggregate(this, seed, func); } public Average(): number { return Average(<any>this); } public All(predicate: (item: TResult) => boolean): boolean { return All(this, predicate); } public Any(predicate?: (item: TResult) => boolean): boolean { return Any(this, predicate); } public Concat(enumerable: Collections.IEnumerable<TResult>): LinqIntermediate<TResult, TResult> { return Concat(this, enumerable); } public Contains(element: TResult, comparer?: IEqualityComparer<TResult>): boolean { return Contains(this, element, comparer); } public Count(predicate?: (item: TResult) => boolean): number { return Count(this, predicate); } public ElementAt(index: number): TResult { return ElementAt(this, index); } public Except(enumerable: Collections.IEnumerable<TResult>, comparer?: IEqualityComparer<TResult>): LinqIntermediate<TResult, TResult> { return Except(this, enumerable, comparer); } public First(predicate?: (item: TResult) => boolean): TResult { return First(this, predicate); } public ForEach(action: (item: TResult) => void): void { ForEach(this, action); } public IndexOf(element: TResult): number { return IndexOf(this, element); } public Intersect(enumerable: Collections.IEnumerable<TResult>, comparer?: IEqualityComparer<TResult>): LinqIntermediate<TResult, TResult> { return Intersect(this, enumerable, comparer); } public LastIndexOf(element: TResult): number { return LastIndexOf(this, element); } public Max(comparer?: IComparer<TResult>): TResult { return Max(this, comparer); } public Min(comparer?: IComparer<TResult>): TResult { return Min(this, comparer); } public Reverse(): LinqIntermediate<TResult, TResult> { return Reverse(this); } public Select<UDes>(func: (item: TResult) => UDes): LinqIntermediate<TResult, UDes> { return Select(this, func); } public SequenceEqual(second: Collections.IEnumerable<TResult>, comparer?: IEqualityComparer<TSource>): boolean { return SequenceEqual(this, second); } public SkipWhile(predicate: (item: TResult, index: number) => boolean): LinqIntermediate<TResult, TResult> { return SkipWhile(this, predicate); } public TakeWhile(predicate: (item: TResult, index: number) => boolean): LinqIntermediate<TResult, TResult> { return TakeWhile(this, predicate); } public ToArray(): TResult[] { return ToArray(this); } public ToDictionary<TKey, TElement>(keyValueSelector: (item: TResult) => Collections.KeyValuePair<TKey, TElement>): Collections.Dictionary<TKey, TElement> { return ToDictionary(this, keyValueSelector); } public ToList(): Collections.List<TResult> { return ToList(this); } public Where(predicate: (item: TResult) => boolean): LinqIntermediate<TResult, TResult> { return Where(this, predicate); } } class LinqEnumerator<TSource, TResult> implements Collections.IEnumerator<TResult> { private toResult: (item: TSource, index: number) => TResult; private enumerator: Collections.IEnumerator<TSource>; private sources: Collections.IEnumerable<TSource>[]; private sourceIndex = 0; private index = -1; constructor(sources: Collections.IEnumerable<TSource>[], toResult: (item: TSource, index: number) => TResult) { this.sources = sources; this.enumerator = sources[this.sourceIndex].GetEnumerator(); this.toResult = toResult; } private SourceMoveNext(): boolean { let next = this.enumerator.MoveNext(); this.index++; return next; } public MoveNext(): boolean { let next = this.SourceMoveNext(); while (next && this.Current === DefaultDelegate.EmptyReturn) { next = this.SourceMoveNext(); } while (!next && ++this.sourceIndex < this.sources.length) { this.enumerator = this.sources[this.sourceIndex].GetEnumerator(); next = this.SourceMoveNext(); } return next; } public get Current(): TResult { return this.toResult(this.enumerator.Current, this.index); } public Reset(): void { this.sourceIndex = 0; this.enumerator = this.sources[this.sourceIndex].GetEnumerator(); } public Dispose(): void { this.enumerator.Dispose(); } } export function Aggregate<TSource, TAccumulate>(source: Collections.IEnumerable<TSource>, seed: TAccumulate, func: (acc: TAccumulate, item: TSource) => TAccumulate): TAccumulate { if (seed == null) throw new ArgumentNullException('seed'); if (func == null) throw new ArgumentNullException('func'); ForEach(source, item => { seed = func(seed, item); }); return seed; } export function Average(source: Collections.IEnumerable<number>): number { if (source == null) throw new ArgumentNullException('source'); let result = 0; let length = 0; let enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { if (typeof enumerator.Current != 'number') throw new ArgumentException('not a number'); length++; result += enumerator.Current; } return result / length; } export function All<TSource>(source: Collections.IEnumerable<TSource>, predicate: (item: TSource) => boolean): boolean { if (source == null) throw new ArgumentNullException('source'); if (predicate == null) throw new ArgumentNullException('predicate'); let enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { if (predicate(enumerator.Current)) continue; return false; } return true; } export function Any<TSource>(source: Collections.IEnumerable<TSource>, predicate?: (item: TSource) => boolean): boolean { if (source == null) throw new ArgumentNullException('source'); predicate = predicate || DefaultDelegate.Predicate; let enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { if (predicate(enumerator.Current)) return true; } return false; } export function Concat<TSource>(first: Collections.IEnumerable<TSource>, second: Collections.IEnumerable<TSource>): LinqIntermediate<TSource, TSource> { if (first == null) throw new ArgumentNullException('first'); if (second == null) throw new ArgumentNullException('second'); let result = [first, second]; let linq = new LinqIntermediate<TSource, TSource>(result, DefaultDelegate.SelfReturn); return linq; } export function Contains<TSource>(source: Collections.IEnumerable<TSource>, element: TSource, comparer?: IEqualityComparer<TSource>): boolean { if (element == null) throw new ArgumentNullException('element'); comparer = comparer || DefaultDelegate.EqualityComparer; return Any(source, item => comparer(item, element)); } export function Count<TSource>(source: Collections.IEnumerable<TSource>, predicate?: (item: TSource) => boolean): number { if (source == null) throw new ArgumentNullException('source'); predicate = predicate || DefaultDelegate.Predicate; let enumerator = source.GetEnumerator(); let count = 0; while (enumerator.MoveNext()) { if (predicate(enumerator.Current)) count++; } return count; } export function ElementAt<TSource>(source: Collections.IEnumerable<TSource>, index: number): TSource { if (source == null) throw new ArgumentNullException('source'); if (index < 0) throw new ArgumentOutOfRangeException('index: ' + index); let enumerator = source.GetEnumerator(); for (let i = 0; i <= index; i++) { if (!enumerator.MoveNext()) throw new ArgumentOutOfRangeException('index: ' + index); } return enumerator.Current; } export function Except<TSource>(first: Collections.IEnumerable<TSource>, second: Collections.IEnumerable<TSource>, comparer?: IEqualityComparer<TSource>): LinqIntermediate<TSource, TSource> { if (first == null) throw new ArgumentNullException('first'); if (second == null) throw new ArgumentNullException('second'); let func = (item: TSource) => { if (!Contains(second, item, comparer)) return item; return DefaultDelegate.EmptyReturn; } let linq = new LinqIntermediate<TSource, TSource>([first], func); return linq; } export function First<TSource>(source: Collections.IEnumerable<TSource>, predicate?: (item: TSource) => boolean): TSource { if (source == null) throw new ArgumentNullException('source'); predicate = predicate || DefaultDelegate.Predicate; let enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { let current = enumerator.Current; if (predicate(current)) return current; } return null; } export function ForEach<TSource>(source: Collections.IEnumerable<TSource>, action: (item: TSource) => void): void { if (source == null) throw new ArgumentNullException('source'); if (action == null) throw new ArgumentNullException('action'); let enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { action(enumerator.Current); } } export function IndexOf<TSource>(source: Collections.IEnumerable<TSource>, element: TSource): number { if (source == null) throw new ArgumentNullException('source'); let enumerator = source.GetEnumerator(); let index = 0; while (enumerator.MoveNext()) { if (element === enumerator.Current) return index; index++; } return -1; } export function Intersect<TSource>(first: Collections.IEnumerable<TSource>, second: Collections.IEnumerable<TSource>, comparer?: IEqualityComparer<TSource>): LinqIntermediate<TSource, TSource> { if (first == null) throw new ArgumentNullException('first'); if (second == null) throw new ArgumentNullException('second'); let func = (item: TSource) => { if (Contains(second, item, comparer)) return item; return DefaultDelegate.EmptyReturn; } let linq = new LinqIntermediate<TSource, TSource>([first], func); return linq; } export function LastIndexOf<TSource>(source: Collections.IEnumerable<TSource>, element: TSource): number { if (source == null) throw new ArgumentNullException('source'); let enumerator = source.GetEnumerator(); let index = 0; let rtn = -1; while (enumerator.MoveNext()) { if (element === enumerator.Current) rtn = index; index++; } return rtn; } export function Max<TSource>(source: Collections.IEnumerable<TSource>, comparer?: IComparer<TSource>): TSource { if (source == null) throw new ArgumentNullException('source'); comparer = comparer || ((a, b) => { if (a === b) return 0; if (a > b) return 1; if (a < b) return -1; return 0; }); let max: TSource = null; let enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { let current = enumerator.Current; if (comparer(max, current) > 0 && current != null) max = current; } return max; } export function Min<TSource>(source: Collections.IEnumerable<TSource>, comparer?: IComparer<TSource>): TSource { let reverseComparer = comparer || ((a, b) => { if (a === b) return 0; if (a > b) return -1; if (a < b) return 1; return 0; }); return Max(source, reverseComparer); } export function Range(start: number, count: number): LinqIntermediate<number, number> { if (start == null) throw new ArgumentNullException('start'); if (count == null) throw new ArgumentNullException('count'); let result: number[] = []; for (let i = start; i < start + count; i++) { result.push(i); } let linq = new LinqIntermediate<number, number>([result], DefaultDelegate.SelfReturn); return linq; } export function Repeat<TResult>(element: TResult, count: number): LinqIntermediate<TResult, TResult> { if (count == null) throw new ArgumentNullException('count'); let result: TResult[] = []; for (let i = 0; i < count; i++) { result.push(element); } let linq = new LinqIntermediate<TResult, TResult>([result], DefaultDelegate.SelfReturn); return linq; } export function Reverse<TSource>(source: Collections.IEnumerable<TSource>): LinqIntermediate<TSource, TSource> { if (source == null) throw new ArgumentNullException('source'); let enumerator = source.GetEnumerator(); let result: TSource[] = []; while (enumerator.MoveNext()) { result.unshift(enumerator.Current); } return LinqStart(result); } export function Select<TSource, TResult>(source: Collections.IEnumerable<TSource>, func: (item: TSource) => TResult): LinqIntermediate<TSource, TResult> { if (source == null) throw new ArgumentNullException('source'); if (func == null) throw new ArgumentNullException('func'); let linq = new LinqIntermediate<TSource, TResult>([source], func); return linq; } export function SequenceEqual<TSource>(first: Collections.IEnumerable<TSource>, second: Collections.IEnumerable<TSource>, comparer?: IEqualityComparer<TSource>): boolean { if (first == null) throw new ArgumentNullException('first'); if (second == null) throw new ArgumentNullException('second'); comparer = comparer || DefaultDelegate.EqualityComparer; let fe = first.GetEnumerator(); let se = second.GetEnumerator(); while (fe.MoveNext()) { if (!se.MoveNext()) return false; if (!comparer(fe.Current, se.Current)) return false; } return !se.MoveNext(); } export function SkipWhile<TSource>(source: Collections.IEnumerable<TSource>, predicate: (item: TSource, index: number) => boolean): LinqIntermediate<TSource, TSource> { if (source == null) throw new ArgumentNullException('source'); if (predicate == null) throw new ArgumentNullException('predicate'); let func: (item: TSource, index: number) => TSource = (item, index) => { if (predicate(item, index)) return DefaultDelegate.EmptyReturn; return item; }; let linq = new LinqIntermediate<TSource, TSource>([source], func); return linq; } export function TakeWhile<TSource>(source: Collections.IEnumerable<TSource>, predicate: (item: TSource, index: number) => boolean): LinqIntermediate<TSource, TSource> { if (source == null) throw new ArgumentNullException('source'); if (predicate == null) throw new ArgumentNullException('predicate'); let func: (item: TSource, index: number) => TSource = (item, index) => { if (predicate(item, index)) return item; return DefaultDelegate.EmptyReturn; }; let linq = new LinqIntermediate<TSource, TSource>([source], func); return linq; } export function ToArray<TSource>(source: Collections.IEnumerable<TSource>): TSource[] { if (source == null) throw new ArgumentNullException('source'); let enumerator = source.GetEnumerator(); let result: TSource[] = []; let i = 0; while (enumerator.MoveNext()) { result[i++] = enumerator.Current; } return result; } export function ToDictionary<TSource, TKey, TElement>(source: Collections.IEnumerable<TSource>, keyValueSelector: (item: TSource) => Collections.KeyValuePair<TKey, TElement>, keyComparer?: IEqualityComparer<TKey>): Collections.Dictionary<TKey, TElement> { if (source == null) throw new ArgumentNullException('source'); if (keyValueSelector == null) throw new ArgumentNullException('keyValueSelector'); // To avoid Dictionary.Resize() let array: TSource[] = ToArray(source); let dict = new Collections.Dictionary<TKey, TElement>(array.length, keyComparer); let enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { let pair = keyValueSelector(enumerator.Current); if (pair == null) continue; dict.Add(pair.Key, pair.Value); } return dict; } export function ToList<TSource>(source: Collections.IEnumerable<TSource>): Collections.List<TSource> { return new Collections.List(ToArray(source)); } export function Where<TSource>(source: Collections.IEnumerable<TSource>, predicate: (item: TSource) => boolean): LinqIntermediate<TSource, TSource> { return TakeWhile(source, predicate); } }