import * as assert from "@esfx/internal-assert" ; import { HashMap } from "@esfx/collections-hashmap" ; import { Equaler } from "@esfx/equatable" ; import { identity } from '@esfx/fn' ; import { Grouping , HierarchyGrouping } from "@esfx/iter-grouping" ; import { HierarchyIterable } from '@esfx/iter-hierarchy' ; import { Page , HierarchyPage } from "@esfx/iter-page" ; import { flowHierarchy } from './internal/utils' ; class PageByIterable < T , R > implements Iterable < R > { private _source : Iterable < T > ; private _pageSize : number ; private _pageSelector : ( page : number , offset : number , values : Iterable < T > ) => R ; constructor ( source , pageSize , pageSelector ) { this . _source = source ; this . _pageSize = pageSize ; this . _pageSelector = pageSelector ; } * [ Symbol . iterator ] ( ) { const source = this . _source ; const pageSize = this . _pageSize ; const pageSelector = this . _pageSelector ; let elements = [ ] ; let page = 0 ; for ( const value of source ) { elements . push ( value ) ; if ( elements . length >= pageSize ) { yield pageSelector ( page , page * pageSize , flowHierarchy ( elements , source ) ) ; elements = [ ] ; page ++ ; } } if ( elements . length > 0 ) { yield pageSelector ( page , page * pageSize , flowHierarchy ( elements , source ) ) ; } } } param source param pageSize category export function pageBy < TNode , T extends TNode > ( source , pageSize ) ; param source param pageSize param pageSelector category export function pageBy < TNode , T extends TNode , R > ( source , pageSize , pageSelector ) ; param source param pageSize category export function pageBy < T > ( source , pageSize ) ; param source param pageSize param pageSelector category export function pageBy < T , R > ( source , pageSize , pageSelector ) ; export function pageBy < T , R > ( source , pageSize , pageSelector = Page . from ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBePositiveNonZeroFiniteNumber ( pageSize , "pageSize" ) ; assert . mustBeFunction ( pageSelector , "pageSelector" ) ; return new PageByIterable ( source , pageSize , pageSelector as ( page : number , offset : number , values : Iterable < T > ) => R ) ; } class SpanMapIterable < T , K , V , R > implements Iterable < R > { private _source : Iterable < T > ; private _keySelector : ( element : T ) => K ; private _keyEqualer : Equaler < K > ; private _elementSelector : ( element : T ) => V ; private _spanSelector : ( key : K , elements : Iterable < T | V > ) => R ; constructor ( source , keySelector , keyEqualer , elementSelector , spanSelector ) { this . _source = source ; this . _keySelector = keySelector ; this . _keyEqualer = keyEqualer ; this . _elementSelector = elementSelector ; this . _spanSelector = spanSelector ; } * [ Symbol . iterator ] ( ) { const source = this . _source ; const keySelector = this . _keySelector ; const keyEqualer = this . _keyEqualer ; const elementSelector = this . _elementSelector ; const spanSelector = this . _spanSelector ; let span ; let previousKey ! ; for ( const element of source ) { const key = keySelector ( element ) ; if ( ! span ) { previousKey = key ; span = [ ] ; } else if ( ! keyEqualer . equals ( previousKey , key ) ) { yield spanSelector ( previousKey , elementSelector === identity ? flowHierarchy ( span , source as Iterable < T | V > ) : span ) ; span = [ ] ; previousKey = key ; } span . push ( elementSelector ( element ) ) ; } if ( span ) { yield spanSelector ( previousKey , elementSelector === identity ? flowHierarchy ( span , source as Iterable < T | V > ) : span ) ; } } } param source param keySelector param keyEqualer category export function spanMap < TNode , T extends TNode , K > ( source , keySelector , keyEqualer ? ) ; param source param keySelector param elementSelector param spanSelector param keyEqualer category export function spanMap < TNode , T extends TNode , K , R > ( source , keySelector , elementSelector , spanSelector , keyEqualer ? ) ; param source param keySelector param keyEqualer category export function spanMap < T , K > ( source , keySelector , keyEqualer ? ) ; param source param keySelector param elementSelector param keyEqualer category export function spanMap < T , K , V > ( source , keySelector , elementSelector , keyEqualer ? ) ; param source param keySelector param elementSelector param spanSelector param keyEqualer category export function spanMap < T , K , V , R > ( source , keySelector , elementSelector , spanSelector , keyEqualer ? ) ; export function spanMap < T , K , V , R > ( source , keySelector , elementSelector = identity , spanSelector = Grouping . from , keyEqualer = Equaler . defaultEqualer ) { if ( typeof elementSelector === "object" ) { keyEqualer = elementSelector ; elementSelector = identity ; } if ( typeof spanSelector === "object" ) { keyEqualer = spanSelector ; spanSelector = Grouping . from ; } assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeFunction ( elementSelector , "elementSelector" ) ; assert . mustBeFunction ( spanSelector , "spanSelector" ) ; assert . mustBeType ( Equaler . hasInstance , keyEqualer , "keyEqualer" ) ; return new SpanMapIterable ( source , keySelector , keyEqualer , elementSelector , spanSelector as ( key : K , span : Iterable < T | V > ) => Grouping < K , T | V > | R ) ; } function createGroupings < T , K , V > ( source , keySelector , elementSelector , keyEqualer ? ) { const map = new HashMap < K , V [ ] > ( keyEqualer ) ; for ( const item of source ) { const key = keySelector ( item ) ; const element = elementSelector ( item ) ; const grouping = map . get ( key ) ; if ( grouping === undefined ) { map . set ( key , [ element ] ) ; } else { grouping . push ( element ) ; } } return map ; } class GroupByIterable < T , K , V , R > implements Iterable < R > { private _source : Iterable < T > ; private _keySelector : ( element : T ) => K ; private _elementSelector : ( element : T ) => T | V ; private _resultSelector : ( key : K , elements : Iterable < T | V > ) => R ; constructor ( source , keySelector , elementSelector , resultSelector ) { this . _source = source ; this . _keySelector = keySelector ; this . _elementSelector = elementSelector ; this . _resultSelector = resultSelector ; } * [ Symbol . iterator ] ( ) { const source = this . _source ; const elementSelector = this . _elementSelector ; const resultSelector = this . _resultSelector ; const map = createGroupings ( source , this . _keySelector , elementSelector ) ; for ( const [ key , values ] of map ) { yield resultSelector ( key , elementSelector === identity ? flowHierarchy ( values , source as Iterable < T | V > ) : values ) ; } } } param source param keySelector param keyEqualer category export function groupBy < TNode , T extends TNode , K > ( source , keySelector , keyEqualer ? ) ; param source param keySelector param elementSelector param resultSelector param keyEqualer category export function groupBy < TNode , T extends TNode , K , R > ( source , keySelector , elementSelector , resultSelector , keyEqualer ? ) ; param source param keySelector param keyEqualer category export function groupBy < T , K > ( source , keySelector , keyEqualer ? ) ; param source param keySelector param elementSelector param keyEqualer category export function groupBy < T , K , V > ( source , keySelector , elementSelector , keyEqualer ? ) ; param source param keySelector param elementSelector param resultSelector param keyEqualer category export function groupBy < T , K , V , R > ( source , keySelector , elementSelector , resultSelector , keyEqualer ? ) ; export function groupBy < T , K , V , R > ( source , keySelector , elementSelector = identity , resultSelector = Grouping . from , keyEqualer ? ) { if ( typeof elementSelector !== "function" ) { resultSelector = elementSelector ; elementSelector = identity ; } if ( typeof resultSelector !== "function" ) { keyEqualer = resultSelector ; resultSelector = Grouping . from ; } assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeFunction ( elementSelector , "elementSelector" ) ; assert . mustBeFunction ( resultSelector , "resultSelector" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , keyEqualer , "keyEqualer" ) ; return new GroupByIterable ( source , keySelector , elementSelector , resultSelector as ( key : K , elements : Iterable < T | V > ) => Grouping < K , T | V > | R ) ; }