@@ -171,23 +171,99 @@ namespace ts {
171171 return result ;
172172 }
173173
174+ /**
175+ * Flattens an array containing a mix of array or non-array elements.
176+ *
177+ * @param array The array to flatten.
178+ */
179+ export function flatten < T > ( array : ( T | T [ ] ) [ ] ) : T [ ] {
180+ let result : T [ ] ;
181+ if ( array ) {
182+ result = [ ] ;
183+ for ( const v of array ) {
184+ if ( v ) {
185+ if ( isArray ( v ) ) {
186+ addRange ( result , v ) ;
187+ }
188+ else {
189+ result . push ( v ) ;
190+ }
191+ }
192+ }
193+ }
194+
195+ return result ;
196+ }
197+
174198 /**
175199 * Maps an array. If the mapped value is an array, it is spread into the result.
200+ *
201+ * @param array The array to map.
202+ * @param mapfn The callback used to map the result into one or more values.
176203 */
177- export function flatMap < T , U > ( array : T [ ] , f : ( x : T , i : number ) => U | U [ ] ) : U [ ] {
204+ export function flatMap < T , U > ( array : T [ ] , mapfn : ( x : T , i : number ) => U | U [ ] ) : U [ ] {
178205 let result : U [ ] ;
179206 if ( array ) {
180207 result = [ ] ;
181208 for ( let i = 0 ; i < array . length ; i ++ ) {
182- const v = array [ i ] ;
183- const ar = f ( v , i ) ;
184- if ( ar ) {
185- // We cast to <U> here to leverage the behavior of Array#concat
186- // which will append a single value here.
187- result = result . concat ( < U [ ] > ar ) ;
209+ const v = mapfn ( array [ i ] , i ) ;
210+ if ( v ) {
211+ if ( isArray ( v ) ) {
212+ addRange ( result , v ) ;
213+ }
214+ else {
215+ result . push ( v ) ;
216+ }
217+ }
218+ }
219+ }
220+ return result ;
221+ }
222+
223+ /**
224+ * Maps contiguous spans of values with the same key.
225+ *
226+ * @param array The array to map.
227+ * @param keyfn A callback used to select the key for an element.
228+ * @param mapfn A callback used to map a contiguous chunk of values to a single value.
229+ */
230+ export function spanMap < T , K , U > ( array : T [ ] , keyfn : ( x : T , i : number ) => K , mapfn : ( chunk : T [ ] , key : K ) => U ) : U [ ] {
231+ let result : U [ ] ;
232+ if ( array ) {
233+ result = [ ] ;
234+ const len = array . length ;
235+ let previousKey : K ;
236+ let key : K ;
237+ let start = 0 ;
238+ let pos = 0 ;
239+ while ( start < len ) {
240+ while ( pos < len ) {
241+ const value = array [ pos ] ;
242+ key = keyfn ( value , pos ) ;
243+ if ( pos === 0 ) {
244+ previousKey = key ;
245+ }
246+ else if ( key !== previousKey ) {
247+ break ;
248+ }
249+
250+ pos ++ ;
188251 }
252+
253+ if ( start < pos ) {
254+ const v = mapfn ( array . slice ( start , pos ) , previousKey ) ;
255+ if ( v ) {
256+ result . push ( v ) ;
257+ }
258+
259+ start = pos ;
260+ }
261+
262+ previousKey = key ;
263+ pos ++ ;
189264 }
190265 }
266+
191267 return result ;
192268 }
193269
0 commit comments