1
+ import * as _ from 'lodash' ;
2
+
3
+ export enum IEList { //these are flags so no direct equals, nothing requires them to be used as flags, but it would allow you to have an entry on both Include and Favorite at the same type
4
+ Invalid = 0 ,
5
+ Include = 1 << 1 ,
6
+ Exclude = 1 << 2 ,
7
+ Favorite = 1 << 3 ,
8
+ }
9
+
10
+ function * mapIterableImpl < T , U > ( f : ( val : T ) => U , iterable : Iterable < T > ) : Iterable < U > {
11
+ for ( const item of iterable ) {
12
+ yield f ( item ) ;
13
+ }
14
+ }
15
+ const mapIterable = < T , U > ( f : ( val : T ) => U ) => ( iterable : Iterable < T > ) => mapIterableImpl ( f , iterable ) ;
16
+ function * filterIterableImpl < T > ( f : ( item : T ) => boolean , iterable : Iterable < T > ) : Iterable < T > {
17
+ for ( const item of iterable ) {
18
+ if ( f ( item ) ) {
19
+ yield item ;
20
+ }
21
+ }
22
+ }
23
+ const filterIterable = < T > ( f : ( val : T ) => boolean ) => ( iterable : Iterable < T > ) => filterIterableImpl ( f , iterable ) ;
24
+
25
+ interface SerializeData < ListKeyType > {
26
+ known : Map < ListKeyType , IEList > ;
27
+ }
28
+ type ItemResolver < T , TResult > = ( value : T ) => TResult ;
29
+
30
+ export class IncludeExcludeList < ListKeyType > {
31
+
32
+ protected known = new Map < ListKeyType , IEList > ( ) ;
33
+
34
+ GetSaveDataObject ( ) : Object {
35
+ return { known :new Map ( this . known ) } as SerializeData < ListKeyType > ;
36
+ }
37
+ static LoadFromSaveDataObject < ListKeyType > ( object : object ) : IncludeExcludeList < ListKeyType > {
38
+ let ret = new IncludeExcludeList < ListKeyType > ( ) ;
39
+ ret . known = new Map ( ( object as SerializeData < ListKeyType > ) . known ) ;
40
+ return ret ;
41
+ }
42
+
43
+ AddOrUpdateToList = ( key : ListKeyType , list : IEList ) => this . known . set ( key , list ) ;
44
+ RemoveFromLists = ( key : ListKeyType ) => this . known . delete ( key ) ;
45
+ ClearList ( list : IEList ) {
46
+ let keys = this . GetKeysOnList ( list ) ;
47
+ for ( const key of keys )
48
+ this . RemoveFromList ( key , list ) ;
49
+ }
50
+ RemoveFromList ( key : ListKeyType , list : IEList ) {
51
+ let current = this . GetKeyList ( key ) ;
52
+ if ( current == undefined )
53
+ return ;
54
+ current &= ~ list ;
55
+ if ( current == IEList . Invalid )
56
+ this . known . delete ( key ) ;
57
+ else
58
+ this . AddOrUpdateToList ( key , current ) ;
59
+ }
60
+
61
+ GetKeyList = ( key : ListKeyType ) => this . known . get ( key ) ;
62
+ GetKeysOnList ( list : IEList ) : ListKeyType [ ] {
63
+ let filtered = filterIterable ( ( kvp : [ ListKeyType , IEList ] ) => ( kvp [ 1 ] & list ) != 0 ) ( this . known . entries ( ) ) ;
64
+ let mapped = mapIterable ( ( kvp : [ ListKeyType , IEList ] ) => kvp [ 0 ] ) ( filtered ) ;
65
+ return Array . from ( mapped ) ;
66
+ }
67
+ IsKeyOnList ( key : ListKeyType , list : IEList , trueIfUnknown : boolean = false ) {
68
+ let val = this . GetKeyList ( key ) ;
69
+ if ( val === undefined )
70
+ return trueIfUnknown ;
71
+ return ( val & list ) != 0 ;
72
+ }
73
+
74
+ /// returnUnknown true if you want items not on any list, false if they should be excluded
75
+ FilterArrayAgainstList < T > ( arr : Iterable < T > , list : IEList , returnUnknown : boolean = false , resolver : ItemResolver < T , ListKeyType > | undefined = undefined ) : Iterable < T > {
76
+ if ( ! resolver )
77
+ resolver = ( itm ) => itm as any ;
78
+ return filterIterable ( ( key : T ) => this . IsKeyOnList ( resolver ! ( key ) , list , returnUnknown ) ) ( arr ) ;
79
+ }
80
+
81
+ /// return the list in the same order passed in except all items that are on the specified list are returned first
82
+ * SortArrayAgainstList < T > ( arr : Iterable < T > , list : IEList , resolver : ItemResolver < T , ListKeyType > | undefined = undefined ) : IterableIterator < T > {
83
+ let after = new Array ( ) as Array < T > ;
84
+ if ( ! resolver )
85
+ resolver = ( itm ) => itm as any ;
86
+ for ( const item of arr ) {
87
+ if ( this . IsKeyOnList ( resolver ( item ) , list ) )
88
+ yield item ;
89
+ else
90
+ after . push ( item ) ;
91
+ }
92
+ for ( const itm of after )
93
+ yield itm ;
94
+ }
95
+
96
+ }
0 commit comments