UNPKG

ix

Version:

The Interactive Extensions for JavaScript

180 lines (163 loc) 6.89 kB
import { IterableX } from '../iterablex.js'; import { sorter as defaultSorter } from '../../util/sorter.js'; import { UnaryFunction } from '../../interfaces.js'; /** @ignore */ export abstract class OrderedIterableBaseX<TSource> extends IterableX<TSource> { _source: Iterable<TSource>; constructor(source: Iterable<TSource>) { super(); this._source = source; } *[Symbol.iterator]() { const array = Array.from<TSource>(this._source); const len = array.length; const indices = new Array<number>(len); for (let i = 0; i < len; i++) { indices[i] = i; } indices.sort(this._getSorter(array)); for (const index of indices) { yield array[index]; } } thenBy<TKey>( keySelector: (item: TSource) => TKey, comparer: (fst: TKey, snd: TKey) => number = defaultSorter ): OrderedIterableBaseX<TSource> { return new OrderedIterableX<TKey, TSource>(this._source, keySelector, comparer, false, this); } thenByDescending<TKey>( keySelector: (item: TSource) => TKey, comparer: (fst: TKey, snd: TKey) => number = defaultSorter ): OrderedIterableBaseX<TSource> { return new OrderedIterableX<TKey, TSource>(this._source, keySelector, comparer, true, this); } abstract _getSorter( elements: TSource[], next?: (x: number, y: number) => number ): (x: number, y: number) => number; } /** @ignore */ /** @ignore */ export class OrderedIterableX<TKey, TSource> extends OrderedIterableBaseX<TSource> { private _keySelector: (item: TSource) => TKey; private _comparer: (fst: TKey, snd: TKey) => number; private _descending: boolean; private _parent?: OrderedIterableBaseX<TSource>; constructor( source: Iterable<TSource>, keySelector: (item: TSource) => TKey, comparer: (fst: TKey, snd: TKey) => number, descending: boolean, parent?: OrderedIterableBaseX<TSource> ) { super(source); this._keySelector = keySelector; this._comparer = comparer; this._descending = descending; this._parent = parent; } _getSorter( elements: TSource[], next?: (x: number, y: number) => number ): (x: number, y: number) => number { const keys = elements.map(this._keySelector); const comparer = this._comparer; const parent = this._parent; const descending = this._descending; const sorter = (x: number, y: number): number => { const result = comparer(keys[x], keys[y]); if (result === 0) { return next ? next(x, y) : x - y; } return descending ? -result : result; }; return parent ? parent._getSorter(elements, sorter) : sorter; } } /** * Sorts the elements of a sequence in ascending order according to a key by using a specified comparer. * * @template TKey The type of the elements of source. * @template TSource The type of the key returned by keySelector. * @param {(item: TSource) => TKey} keySelector A function to extract a key from an element. * @param {(fst: TKey, snd: TKey) => number} [comparer=defaultSorter] A comparer to compare keys. * @returns {UnaryFunction<Iterable<TSource>, OrderedIterableX<TKey, TSource>>} An ordered iterable sequence whose * elements are sorted according to a key and comparer. */ export function orderBy<TKey, TSource>( keySelector: (item: TSource) => TKey, comparer: (fst: TKey, snd: TKey) => number = defaultSorter ): UnaryFunction<Iterable<TSource>, OrderedIterableX<TKey, TSource>> { return function orderByOperatorFunction(source: Iterable<TSource>) { return new OrderedIterableX<TKey, TSource>(source, keySelector, comparer, false); }; } /** * Sorts the elements of a sequence in descending order according to a key by using a specified comparer. * * @template TKey The type of the elements of source. * @template TSource The type of the key returned by keySelector. * @param {(item: TSource) => TKey} keySelector A function to extract a key from an element. * @param {(fst: TKey, snd: TKey) => number} [comparer=defaultSorter] A comparer to compare keys. * @returns {UnaryFunction<Iterable<TSource>, OrderedIterableX<TKey, TSource>>} An ordered iterable sequence whose * elements are sorted in descending order according to a key and comparer. */ export function orderByDescending<TKey, TSource>( keySelector: (item: TSource) => TKey, comparer: (fst: TKey, snd: TKey) => number = defaultSorter ): UnaryFunction<Iterable<TSource>, OrderedIterableX<TKey, TSource>> { return function orderByDescendingOperatorFunction(source: Iterable<TSource>) { return new OrderedIterableX<TKey, TSource>(source, keySelector, comparer, true); }; } /** * Performs a subsequent ordering of the elements in a sequence in ascending order according to a key using a specified comparer. * * @template TKey The type of the elements of source. * @template TSource The type of the key returned by keySelector. * @param {(item: TSource) => TKey} keySelector A function to extract a key from an element. * @param {(fst: TKey, snd: TKey) => number} [comparer=defaultSorter] A comparer to compare keys. * @returns {UnaryFunction<Iterable<TSource>, OrderedIterableX<TKey, TSource>>} An ordered iterable whose elements are * sorted according to a key and comparer. */ export function thenBy<TKey, TSource>( keySelector: (item: TSource) => TKey, comparer: (fst: TKey, snd: TKey) => number = defaultSorter ): UnaryFunction<Iterable<TSource>, OrderedIterableX<TKey, TSource>> { return function thenByOperatorFunction(source: Iterable<TSource>) { const orderSource = <OrderedIterableBaseX<TSource>>source; return new OrderedIterableX<TKey, TSource>( orderSource._source, keySelector, comparer, false, orderSource ); }; } /** * Performs a subsequent ordering of the elements in a sequence in descending order according to a key using a specified comparer. * * @template TKey The type of the elements of source. * @template TSource The type of the key returned by keySelector. * @param {(item: TSource) => TKey} keySelector A function to extract a key from an element. * @param {(fst: TKey, snd: TKey) => number} [comparer=defaultSorter] A comparer to compare keys. * @returns {UnaryFunction<Iterable<TSource>, OrderedIterableX<TKey, TSource>>} An ordered iterable whose elements are * sorted in descending order according to a key and comparer. */ export function thenByDescending<TKey, TSource>( keySelector: (item: TSource) => TKey, comparer: (fst: TKey, snd: TKey) => number = defaultSorter ): UnaryFunction<Iterable<TSource>, OrderedIterableX<TKey, TSource>> { return function thenByDescendingOperatorFunction(source: Iterable<TSource>) { const orderSource = <OrderedIterableBaseX<TSource>>source; return new OrderedIterableX<TKey, TSource>( orderSource._source, keySelector, comparer, true, orderSource ); }; }