1import { vectorToArray } from './vectorToArray'; 2import { Vector } from '../types'; 3 4/** @public */ 5export abstract class FunctionalVector<T = any> implements Vector<T>, Iterable<T> { 6 abstract get length(): number; 7 8 abstract get(index: number): T; 9 10 // Implement "iterator protocol" 11 *iterator() { 12 for (let i = 0; i < this.length; i++) { 13 yield this.get(i); 14 } 15 } 16 17 // Implement "iterable protocol" 18 [Symbol.iterator]() { 19 return this.iterator(); 20 } 21 22 forEach(iterator: (row: T) => void) { 23 return vectorator(this).forEach(iterator); 24 } 25 26 map<V>(transform: (item: T, index: number) => V) { 27 return vectorator(this).map(transform); 28 } 29 30 filter(predicate: (item: T) => boolean): T[] { 31 return vectorator(this).filter(predicate); 32 } 33 34 toArray(): T[] { 35 return vectorToArray(this); 36 } 37 38 toJSON(): any { 39 return this.toArray(); 40 } 41} 42 43/** 44 * Use functional programming with your vector 45 */ 46export function vectorator<T>(vector: Vector<T>) { 47 return { 48 *[Symbol.iterator]() { 49 for (let i = 0; i < vector.length; i++) { 50 yield vector.get(i); 51 } 52 }, 53 54 forEach(iterator: (row: T) => void) { 55 for (let i = 0; i < vector.length; i++) { 56 iterator(vector.get(i)); 57 } 58 }, 59 60 map<V>(transform: (item: T, index: number) => V) { 61 const result: V[] = []; 62 for (let i = 0; i < vector.length; i++) { 63 result.push(transform(vector.get(i), i)); 64 } 65 return result; 66 }, 67 68 /** Add a predicate where you return true if it should *keep* the value */ 69 filter(predicate: (item: T) => boolean): T[] { 70 const result: T[] = []; 71 for (const val of this) { 72 if (predicate(val)) { 73 result.push(val); 74 } 75 } 76 return result; 77 }, 78 }; 79} 80