import { Grouping } from "../../sync/Grouping" ; import { IAsyncEnumerable , IEqualityComparer , IGrouping , SelectorKeyType } from "../../types" ; import { BasicAsyncEnumerable } from "../BasicAsyncEnumerable" ; type GroupByWithSelFunc = { param source param keySelector param elementSelector returns < TSource , TKey extends SelectorKeyType , TElement > ( source , keySelector , elementSelector ) : IAsyncEnumerable < IGrouping < TKey , TElement > > ; param source param keySelector param elementSelector param comparer returns < TSource , TKey , TElement > ( source , keySelector , elementSelector , comparer ) : IAsyncEnumerable < IGrouping < TKey , TElement > > ; } ; export const groupByWithSel = < TSource , TKey , TElement > ( source , keySelector , elementSelector , comparer ? ) : IAsyncEnumerable < IGrouping < any , TElement > > => { if ( comparer ) { return groupBy1 ( source , keySelector as ( x : TSource ) => TKey , elementSelector , comparer ) ; } else { return groupBy1Simple ( source , keySelector as ( x : TSource ) => number | string , elementSelector ) ; } } ; const groupBy1Simple = < TSource , TKey extends SelectorKeyType , TElement > ( source , keySelector , elementSelector ) : IAsyncEnumerable < IGrouping < TKey , TElement > > => { async function * generate ( ) { const keyMap = { } ; for await ( const value of source ) { const key = keySelector ( value ) ; const grouping = keyMap [ key ] ; const element = elementSelector ( value ) ; if ( grouping ) { grouping . push ( element ) ; } else { keyMap [ key ] = new Grouping < TKey , TElement > ( key , element ) ; } } for ( const value in keyMap ) { yield keyMap [ value ] ; } } return new BasicAsyncEnumerable ( generate ) ; } ; const groupBy1 = < TSource , TKey , TElement > ( source , keySelector , elementSelector , comparer ) : IAsyncEnumerable < IGrouping < TKey , TElement > > => { async function * generate ( ) { const keyMap = new Array < Grouping < TKey , TElement > > ( ) ; for await ( const value of source ) { const key = keySelector ( value ) ; let found = false ; for ( let i = 0 ; i < keyMap . length ; i ++ ) { const group = keyMap [ i ] ; if ( comparer ( group . key , key ) ) { group . push ( elementSelector ( value ) ) ; found = true ; break ; } } if ( found === false ) { const element = elementSelector ( value ) ; keyMap . push ( new Grouping < TKey , TElement > ( key , element ) ) ; } } for ( const value of keyMap ) { yield value ; } } return new BasicAsyncEnumerable ( generate ) ; } ;