upsetjs import type { ISet , ISetCombination , ISetLike , ISets , SetCombinationType } from '../model' ; import { postprocessCombinations , SortCombinationOrder , SortCombinationOrders } from './asCombinations' ; import { postprocessSets , SortSetOrder } from './asSets' ; import { SET_JOINERS } from './constants' ; export interface ExtractFromExpressionOptions { type ? : SetCombinationType ; setOrder ? : SortSetOrder ; combinationOrder ? : SortCombinationOrder | SortCombinationOrders ; joiner ? : string ; param set toKey ? : ( set : ISetLike < unknown > ) => string ; } param combinations param accessor param options export default function extractFromExpression < T extends { cardinality : number ; } > ( combinations , accessor , options ? ) ; param combinations param options export default function extractFromExpression < T extends { sets : string [ ] ; cardinality : number ; } > ( combinations , options ? ) ; export default function extractFromExpression < T extends { cardinality : number ; } > ( combinations , accOrOptions ? , o = { } ) { const acc = typeof accOrOptions === 'function' ? accOrOptions : ( e ) => ( e as unknown as { sets : string [ ] ; } ) . sets ; const options = ( typeof accOrOptions !== 'function' ? accOrOptions : o ) ?? { } ; const type = options . type ?? 'intersection' ; const joiner = options . joiner ?? SET_JOINERS [ type ] ; const sets = [ ] ; const setLookup = new Map < string , ISet < unknown > > ( ) ; const cs = combinations . map ( ( c ) => { const containedSets = acc ( c ) ; const containedSetsObjects = containedSets . map ( ( s ) => { if ( setLookup . has ( s ) ) { return setLookup . get ( s ) ! ; } const set = { cardinality : 0 , elems : [ ] , name : s , type : 'set' , } ; sets . push ( set ) ; setLookup . set ( set . name , set ) ; return set ; } ) ; if ( type === 'distinctIntersection' ) { for ( const s of containedSetsObjects ) { ( s as { cardinality : number ; } ) . cardinality += c . cardinality ; } } else if ( containedSets . length === 1 ) { Object . assign ( containedSetsObjects [ 0 ] , { cardinality : c . cardinality , } , c ) ; } else if ( type === 'intersection' ) { for ( const s of containedSetsObjects ) { ( s as { cardinality : number ; } ) . cardinality = Math . max ( s . cardinality , c . cardinality ) ; } } else if ( type === 'union' ) { for ( const s of containedSetsObjects ) { ( s as { cardinality : number ; } ) . cardinality = Math . min ( s . cardinality , c . cardinality ) ; } } const name = containedSets . join ( joiner ) ; return Object . assign ( { type , elems : [ ] , name , } , c , { cardinality : c . cardinality , degree : containedSets . length , sets : new Set ( containedSetsObjects ) , } ) ; } ) ; const sortedSets = postprocessSets ( sets , { order : options . setOrder , } ) ; const sortedCombinations = postprocessCombinations ( sortedSets , cs , { order : options . combinationOrder , } ) ; return { sets : sortedSets , combinations : sortedCombinations , } ; }