@@ -1140,13 +1140,26 @@ namespace ts {
1140
1140
* @param offset An offset into `array` at which to start the search.
1141
1141
*/
1142
1142
export function binarySearch < T , U > ( array : ReadonlyArray < T > , value : T , keySelector : ( v : T ) => U , keyComparer : Comparer < U > , offset ?: number ) : number {
1143
- if ( ! array || array . length === 0 ) {
1143
+ return some ( array ) ? binarySearchKey ( array , keySelector ( value ) , keySelector , keyComparer , offset ) : - 1 ;
1144
+ }
1145
+
1146
+ /**
1147
+ * Performs a binary search, finding the index at which an object with `key` occurs in `array`.
1148
+ * If no such index is found, returns the 2's-complement of first index at which
1149
+ * `array[index]` exceeds `key`.
1150
+ * @param array A sorted array whose first element must be no larger than number
1151
+ * @param key The key to be searched for in the array.
1152
+ * @param keySelector A callback used to select the search key from each element of `array`.
1153
+ * @param keyComparer A callback used to compare two keys in a sorted array.
1154
+ * @param offset An offset into `array` at which to start the search.
1155
+ */
1156
+ export function binarySearchKey < T , U > ( array : ReadonlyArray < T > , key : U , keySelector : ( v : T ) => U , keyComparer : Comparer < U > , offset ?: number ) : number {
1157
+ if ( ! some ( array ) ) {
1144
1158
return - 1 ;
1145
1159
}
1146
1160
1147
1161
let low = offset || 0 ;
1148
1162
let high = array . length - 1 ;
1149
- const key = keySelector ( value ) ;
1150
1163
while ( low <= high ) {
1151
1164
const middle = low + ( ( high - low ) >> 1 ) ;
1152
1165
const midKey = keySelector ( array [ middle ] ) ;
@@ -2130,4 +2143,74 @@ namespace ts {
2130
2143
deleted ( oldItems [ oldIndex ++ ] ) ;
2131
2144
}
2132
2145
}
2146
+
2147
+ /**
2148
+ * A list of sorted and unique values. Optimized for best performance when items are added
2149
+ * in the sort order.
2150
+ */
2151
+ export class SortedUniqueList < T > implements Push < T > {
2152
+ private relationalComparer : ( a : T , b : T ) => Comparison ;
2153
+ private equalityComparer : ( a : T , b : T ) => boolean ;
2154
+ private sortedAndUnique = true ;
2155
+ private copyOnWrite = false ;
2156
+ private unsafeArray : T [ ] = [ ] ;
2157
+ private unsafeLast : T | undefined = undefined ;
2158
+
2159
+ constructor ( relationalComparer : Comparer < T > , equalityComparer : EqualityComparer < T > ) {
2160
+ this . relationalComparer = relationalComparer ;
2161
+ this . equalityComparer = equalityComparer ;
2162
+ }
2163
+
2164
+ get size ( ) {
2165
+ return this . unsafeArray . length ;
2166
+ }
2167
+
2168
+ get last ( ) {
2169
+ this . ensureSortedAndUnique ( ) ;
2170
+ return this . unsafeLast === undefined
2171
+ ? this . unsafeLast = lastOrUndefined ( this . unsafeArray )
2172
+ : this . unsafeLast ;
2173
+ }
2174
+
2175
+ push ( ...values : T [ ] ) {
2176
+ for ( const value of values ) {
2177
+ if ( this . sortedAndUnique ) {
2178
+ const last = this . last ;
2179
+ if ( last === undefined || this . relationalComparer ( value , last ) > 0 ) {
2180
+ this . unsafeAdd ( value , /*sortedAndUnique*/ true ) ;
2181
+ continue ;
2182
+ }
2183
+ if ( this . equalityComparer ( value , last ) ) {
2184
+ continue ;
2185
+ }
2186
+ }
2187
+ this . unsafeAdd ( value , /*sortedAndUnique*/ false ) ;
2188
+ }
2189
+ }
2190
+
2191
+ toArray ( ) : ReadonlyArray < T > {
2192
+ this . ensureSortedAndUnique ( ) ;
2193
+ this . copyOnWrite = true ;
2194
+ return this . unsafeArray ;
2195
+ }
2196
+
2197
+ private unsafeAdd ( value : T , sortedAndUnique : boolean ) {
2198
+ if ( this . copyOnWrite ) {
2199
+ this . unsafeArray = this . unsafeArray . slice ( ) ;
2200
+ this . copyOnWrite = false ;
2201
+ }
2202
+
2203
+ this . unsafeArray . push ( value ) ;
2204
+ this . unsafeLast = sortedAndUnique ? value : undefined ;
2205
+ this . sortedAndUnique = sortedAndUnique ;
2206
+ }
2207
+
2208
+ private ensureSortedAndUnique ( ) {
2209
+ if ( ! this . sortedAndUnique ) {
2210
+ this . unsafeArray = deduplicateSorted ( stableSort ( this . unsafeArray , this . relationalComparer ) , this . equalityComparer ) ;
2211
+ this . unsafeLast = undefined ;
2212
+ this . sortedAndUnique = true ;
2213
+ }
2214
+ }
2215
+ }
2133
2216
}
0 commit comments