import * as assert from "@esfx/internal-assert" ; import { Comparer , Comparison } from "@esfx/equatable" ; import { OrderedIterable } from "@esfx/iter-ordered" ; import { HierarchyIterable , OrderedHierarchyIterable } from '@esfx/iter-hierarchy' ; import { toArray } from './scalars' ; import { flowHierarchy } from './internal/utils' ; class ReverseIterable < T > implements Iterable < T > { private _source : Iterable < T > ; constructor ( source ) { this . _source = source ; } * [ Symbol . iterator ] ( ) { const list = toArray < T > ( this . _source ) ; list . reverse ( ) ; yield * list ; } } category export function reverse < TNode , T extends TNode > ( source ) ; category export function reverse < T > ( source ) ; export function reverse < T > ( source ) { assert . mustBeIterableObject ( source , "source" ) ; return flowHierarchy ( new ReverseIterable ( source ) , source ) ; } class OrderByIterable < T , K > implements OrderedIterable < T > { private _source : Iterable < T > ; private _keySelector : ( element : T ) => K ; private _keyComparer : Comparer < K > ; private _descending : boolean ; private _parent ? : OrderByIterable < T , any > ; constructor ( source , keySelector , keyComparer , descending , parent ? ) { this . _source = source ; this . _keySelector = keySelector ; this . _keyComparer = keyComparer ; this . _descending = descending ; this . _parent = parent ; } * [ Symbol . iterator ] ( ) { const source = this . _source ; const array = toArray < T > ( source ) ; const sorter = this . _getSorter ( array ) ; const len = array . length ; const indices = new Array < number > ( len ) ; for ( let i = 0 ; i < len ; ++ i ) { indices [ i ] = i ; } indices . sort ( sorter ) ; for ( const index of indices ) { yield array [ index ] ; } } [ OrderedIterable . thenBy ] < K > ( keySelector , keyComparer , descending ) { if ( typeof keyComparer === "function" ) keyComparer = Comparer . create ( keyComparer ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeType ( Comparer . hasInstance , keyComparer , "keyComparer" ) ; assert . mustBeBoolean ( descending , "descending" ) ; return new OrderByIterable ( this . _source , keySelector , keyComparer , descending , this ) ; } private _getSorter ( elements , next ? ) { const keySelector = this . _keySelector ; const comparer = this . _keyComparer ; const descending = this . _descending ; const parent = this . _parent ; const keys = elements . map ( keySelector ) ; const sorter = ( x , y ) : number => { const result = comparer . compare ( 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 ; } } param source param keySelector param keyComparer category export function orderBy < TNode , T extends TNode , K > ( source , keySelector , keyComparer ? ) ; param source param keySelector param keyComparer category export function orderBy < T , K > ( source , keySelector , keyComparer ? ) ; export function orderBy < T , K > ( source , keySelector , keyComparer = Comparer . defaultComparer ) { if ( typeof keyComparer === "function" ) keyComparer = Comparer . create ( keyComparer ) ; assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeType ( Comparer . hasInstance , keyComparer , "keyComparer" ) ; return flowHierarchy ( new OrderByIterable ( source , keySelector , keyComparer , false ) , source ) ; } param source param keySelector param keyComparer category export function orderByDescending < TNode , T extends TNode , K > ( source , keySelector , keyComparer ? ) ; param source param keySelector param keyComparer category export function orderByDescending < T , K > ( source , keySelector , keyComparer ? ) ; export function orderByDescending < T , K > ( source , keySelector , keyComparer = Comparer . defaultComparer ) { if ( typeof keyComparer === "function" ) keyComparer = Comparer . create ( keyComparer ) ; assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeType ( Comparer . hasInstance , keyComparer , "keyComparer" ) ; return flowHierarchy ( new OrderByIterable ( source , keySelector , keyComparer , true ) , source ) ; } param source param keySelector param keyComparer category export function thenBy < TNode , T extends TNode , K > ( source , keySelector , keyComparer ? ) ; param source param keySelector param keyComparer category export function thenBy < T , K > ( source , keySelector , keyComparer ? ) ; export function thenBy < T , K > ( source , keySelector , keyComparer = Comparer . defaultComparer ) { if ( typeof keyComparer === "function" ) keyComparer = Comparer . create ( keyComparer ) ; assert . mustBeType ( OrderedIterable . hasInstance , source , "source" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeType ( Comparer . hasInstance , keyComparer , "keyComparer" ) ; return flowHierarchy ( source [ OrderedIterable . thenBy ] ( keySelector , keyComparer , false ) , source ) ; } param source param keySelector param keyComparer category export function thenByDescending < TNode , T extends TNode , K > ( source , keySelector , keyComparer ? ) ; param source param keySelector param keyComparer category export function thenByDescending < T , K > ( source , keySelector , keyComparer ? ) ; export function thenByDescending < T , K > ( source , keySelector , keyComparer = Comparer . defaultComparer ) { if ( typeof keyComparer === "function" ) keyComparer = Comparer . create ( keyComparer ) ; assert . mustBeType ( OrderedIterable . hasInstance , source , "source" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeType ( Comparer . hasInstance , keyComparer , "keyComparer" ) ; return flowHierarchy ( source [ OrderedIterable . thenBy ] ( keySelector , keyComparer , true ) , source ) ; }