All files Sequence.ts

100% Statements 69/69
100% Branches 8/8
100% Functions 18/18
100% Lines 62/62
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 17113x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x   13x               141x 98x 43x 20x   23x 4x 8x                 13x 34x 113x 113x   34x             13x 2x 2x 6x 6x 2x 2x   4x     2x             13x 1x 3x 3x               13x 2x               13x 1x             13x 1x             13x 1x               13x 1x             13x 1x                 13x 2x               13x 1x               13x 2x               13x 1x           13x 4x   13x   13x  
import { Collection, isIterable } from './utils'
import repeat from './repeat'
import zip from './zip'
import append from './append'
import map from './map'
import flatMap from './flatMap'
import filter from './filter'
import take from './take'
import takeWhile from './takeWhile'
import drop from './drop'
import dropWhile from './dropWhile'
import reduce from './reduce'
 
class Sequence<T> implements Iterable<T> {
  [Symbol.iterator]: () => Iterator<T>
 
  /**
   * Creates a new Sequence
   * @param collection A collection to form the sequence from
   */
  constructor(collection: Collection<T>) {
    if(typeof collection === 'function') {
      this[Symbol.iterator] = collection
    } else if(isIterable(collection)) {
      this[Symbol.iterator] = () => collection[Symbol.iterator]()
    } else {
      this[Symbol.iterator] = function* () {
        for(let i = 0; i < collection.length; i++) {
          yield collection[i]
        }
      }
    }
  }
 
  /**
   * Return an array with the elements of this Sequence
   */
  toArray(): T[] {
    const result = []
    for(const value of this) {
      result.push(value)
    }
    return result
  }
 
  /**
   * Return a string formed by concatenating the string representation of the elements of this Sequence
   * @param separator A string that will be used between the Sequence elements. Defaults to empty string
   */
  join(separator = '') {
    let result = ''
    let first = true
    for(const value of this) {
      if(first) {
        result += value
        first = false
      } else {
        result += separator + value
      }
    }
    return result
  }
 
  /**
   * For each element of this Sequence call the supplied function with the value and index of this element.
   * @param fn The function to call with the values and indices of the elements of this Sequence.
   */
  forEach(fn: (value: T, index: number) => any) {
    let index = 0
    for(const value of this) {
      fn(value, index++)
    }
  }
 
  /**
   * Return a Sequence whose elements are the elements of this Sequence repeated the specified number of times.
   * @param times The number of times the elements are repeated. Defaults to Infinity
   */
  repeat(times?: number) {
    return repeat(this, times)
  }
 
  /**
   * Return a Sequence whose elements are two element arrays created from the elements of this Sequence and
   * the collection passed as arguments. The length of the sequence is equal to the length of the shorter collection.
   * @param collection A Collection to zip
   */
  zip<U>(collection: Collection<U>) {
    return zip(this, collection)
  }
 
  /**
   * Return a Sequence consisting of elements from this Sequence followed by the elements from the Collection.
   * @param collection A Collection to use when forming the resulting sequence.
   */
  append<U>(collection: Collection<U>) {
    return append(this, collection)
  }
 
  /**
   * Return a new Sequence that contains the elements created from the elements of this Sequence.
   * @param fn A function that produces an element of the new Sequence using an element of the old collection.
   */
  map<U>(fn: (value: T, index: number) => U) {
    return map(this, fn)
  }
 
  /**
   * Return a new Sequence that contains the elements of flattened collections created from the elements
   * of this Sequence.
   * @param fn A function that produces an element of the new Sequence using an element of the old collection.
   */
  flatMap<U>(fn: (value: T, index: number) => Collection<U>) {
    return flatMap(this, fn)
  }
 
  /**
   * Return a new Sequence that contains the elements from this Sequence that satisfy the predicate.
   * @param predicate A function that tests if a value satisfies some condition.
   */
  filter(predicate: (value: T, index: number) => boolean) {
    return filter(this, predicate)
  }
 
  /**
   * Return a Sequence that contains the first elements of this sequence. The argument specifies the
   * number of elements to take. If the length of this sequence is smaller, all of the sequence elements
   * will be present in the resulting sequence.
   * @param count The number of elements to take.
   */
  take(count: number) {
    return take(this, count)
  }
 
  /**
   * Return a new Sequence that contains the elements from this Sequence that occur before the element that no
   * longer satisfies the predicate.
   * @param predicate A function that tests if a value satisfies some condition.
   */
  takeWhile(predicate: (value: T, index: number) => boolean) {
    return takeWhile(this, predicate)
  }
 
  /**
   * Return a Sequence that contains the elements of this sequence without the first elements. The argument
   * specifies the number of elements to omit.
   * @param count The number of elements to omit.
  */
  drop(count: number) {
    return drop(this, count)
  }
 
  /**
   * Return a Sequence that contains the elements from this Sequence that occur after the first element that
   * satisfies the predicate including that element.
   * @param predicate A function that tests if a value satisfies some condition.
   */
  dropWhile(predicate: (value: T, index: number) => boolean) {
    return dropWhile(this, predicate)
  }
  /**
   * Apply a function against an accumulator and each element of this Sequence to reduce it to a single value.
   * @param fn A function that uses an accumulator and an element and reduces them to a single value.
   */
  reduce(fn: (accumulator: T, value: T, index: number) => T) {
    return reduce(this, fn)
  }
}
 
export default Sequence