|
| 1 | +//Copied unexported functions from @angular/core/src/facade/collection |
| 2 | +import { |
| 3 | + isJsObject, isArray, getSymbolIterator, |
| 4 | + isPresent, isBlank |
| 5 | +} from "./lang-facade"; |
| 6 | + |
| 7 | +export function isListLikeIterable(obj: any): boolean { |
| 8 | + if (!isJsObject(obj)) return false; |
| 9 | + return isArray(obj) || |
| 10 | + (!(obj instanceof Map) && // JS Map are iterables but return entries as [k, v] |
| 11 | + getSymbolIterator() in obj); // JS Iterable have a Symbol.iterator prop |
| 12 | +} |
| 13 | + |
| 14 | +export class ListWrapper { |
| 15 | + // JS has no way to express a statically fixed size list, but dart does so we |
| 16 | + // keep both methods. |
| 17 | + static createFixedSize(size: number): any[] { return new Array(size); } |
| 18 | + static createGrowableSize(size: number): any[] { return new Array(size); } |
| 19 | + static clone<T>(array: T[]): T[] { return array.slice(0); } |
| 20 | + static forEachWithIndex<T>(array: T[], fn: (t: T, n: number) => void) { |
| 21 | + for (var i = 0; i < array.length; i++) { |
| 22 | + fn(array[i], i); |
| 23 | + } |
| 24 | + } |
| 25 | + static first<T>(array: T[]): T { |
| 26 | + if (!array) return null; |
| 27 | + return array[0]; |
| 28 | + } |
| 29 | + static last<T>(array: T[]): T { |
| 30 | + if (!array || array.length == 0) return null; |
| 31 | + return array[array.length - 1]; |
| 32 | + } |
| 33 | + static indexOf<T>(array: T[], value: T, startIndex: number = 0): number { |
| 34 | + return array.indexOf(value, startIndex); |
| 35 | + } |
| 36 | + static contains<T>(list: T[], el: T): boolean { return list.indexOf(el) !== -1; } |
| 37 | + static reversed<T>(array: T[]): T[] { |
| 38 | + var a = ListWrapper.clone(array); |
| 39 | + return a.reverse(); |
| 40 | + } |
| 41 | + static concat(a: any[], b: any[]): any[] { return a.concat(b); } |
| 42 | + static insert<T>(list: T[], index: number, value: T) { list.splice(index, 0, value); } |
| 43 | + static removeAt<T>(list: T[], index: number): T { |
| 44 | + var res = list[index]; |
| 45 | + list.splice(index, 1); |
| 46 | + return res; |
| 47 | + } |
| 48 | + static removeAll<T>(list: T[], items: T[]) { |
| 49 | + for (var i = 0; i < items.length; ++i) { |
| 50 | + var index = list.indexOf(items[i]); |
| 51 | + list.splice(index, 1); |
| 52 | + } |
| 53 | + } |
| 54 | + static remove<T>(list: T[], el: T): boolean { |
| 55 | + var index = list.indexOf(el); |
| 56 | + if (index > -1) { |
| 57 | + list.splice(index, 1); |
| 58 | + return true; |
| 59 | + } |
| 60 | + return false; |
| 61 | + } |
| 62 | + static clear(list: any[]) { list.length = 0; } |
| 63 | + static isEmpty(list: any[]): boolean { return list.length == 0; } |
| 64 | + static fill(list: any[], value: any, start: number = 0, end: number = null) { |
| 65 | + (<any>list).fill(value, start, end === null ? list.length : end); |
| 66 | + } |
| 67 | + static equals(a: any[], b: any[]): boolean { |
| 68 | + if (a.length != b.length) return false; |
| 69 | + for (var i = 0; i < a.length; ++i) { |
| 70 | + if (a[i] !== b[i]) return false; |
| 71 | + } |
| 72 | + return true; |
| 73 | + } |
| 74 | + static slice<T>(l: T[], from: number = 0, to: number = null): T[] { |
| 75 | + return l.slice(from, to === null ? undefined : to); |
| 76 | + } |
| 77 | + static splice<T>(l: T[], from: number, length: number): T[] { return l.splice(from, length); } |
| 78 | + static sort<T>(l: T[], compareFn?: (a: T, b: T) => number) { |
| 79 | + if (isPresent(compareFn)) { |
| 80 | + l.sort(compareFn); |
| 81 | + } else { |
| 82 | + l.sort(); |
| 83 | + } |
| 84 | + } |
| 85 | + static toString<T>(l: T[]): string { return l.toString(); } |
| 86 | + static toJSON<T>(l: T[]): string { return JSON.stringify(l); } |
| 87 | + |
| 88 | + static maximum<T>(list: T[], predicate: (t: T) => number): T { |
| 89 | + if (list.length == 0) { |
| 90 | + return null; |
| 91 | + } |
| 92 | + var solution: any /** TODO #???? */ = null; |
| 93 | + var maxValue = -Infinity; |
| 94 | + for (var index = 0; index < list.length; index++) { |
| 95 | + var candidate = list[index]; |
| 96 | + if (isBlank(candidate)) { |
| 97 | + continue; |
| 98 | + } |
| 99 | + var candidateValue = predicate(candidate); |
| 100 | + if (candidateValue > maxValue) { |
| 101 | + solution = candidate; |
| 102 | + maxValue = candidateValue; |
| 103 | + } |
| 104 | + } |
| 105 | + return solution; |
| 106 | + } |
| 107 | + |
| 108 | + static flatten<T>(list: Array<T|T[]>): T[] { |
| 109 | + var target: any[] = []; |
| 110 | + _flattenArray(list, target); |
| 111 | + return target; |
| 112 | + } |
| 113 | + |
| 114 | + static addAll<T>(list: Array<T>, source: Array<T>): void { |
| 115 | + for (var i = 0; i < source.length; i++) { |
| 116 | + list.push(source[i]); |
| 117 | + } |
| 118 | + } |
| 119 | +} |
| 120 | + |
| 121 | +function _flattenArray(source: any[], target: any[]): any[] { |
| 122 | + if (isPresent(source)) { |
| 123 | + for (var i = 0; i < source.length; i++) { |
| 124 | + var item = source[i]; |
| 125 | + if (isArray(item)) { |
| 126 | + _flattenArray(item, target); |
| 127 | + } else { |
| 128 | + target.push(item); |
| 129 | + } |
| 130 | + } |
| 131 | + } |
| 132 | + return target; |
| 133 | +} |
| 134 | + |
| 135 | +export class StringMapWrapper { |
| 136 | + static create(): {[k: /*any*/ string]: any} { |
| 137 | + // Note: We are not using Object.create(null) here due to |
| 138 | + // performance! |
| 139 | + // http://jsperf.com/ng2-object-create-null |
| 140 | + return {}; |
| 141 | + } |
| 142 | + static contains(map: {[key: string]: any}, key: string): boolean { |
| 143 | + return map.hasOwnProperty(key); |
| 144 | + } |
| 145 | + static get<V>(map: {[key: string]: V}, key: string): V { |
| 146 | + return map.hasOwnProperty(key) ? map[key] : undefined; |
| 147 | + } |
| 148 | + static set<V>(map: {[key: string]: V}, key: string, value: V) { map[key] = value; } |
| 149 | + |
| 150 | + static keys(map: {[key: string]: any}): string[] { return Object.keys(map); } |
| 151 | + static values<T>(map: {[key: string]: T}): T[] { |
| 152 | + return Object.keys(map).map((k: string): T => map[k]); |
| 153 | + } |
| 154 | + static isEmpty(map: {[key: string]: any}): boolean { |
| 155 | + for (var prop in map) { |
| 156 | + return false; |
| 157 | + } |
| 158 | + return true; |
| 159 | + } |
| 160 | + static delete (map: {[key: string]: any}, key: string) { delete map[key]; } |
| 161 | + static forEach<K, V>(map: {[key: string]: V}, callback: (v: V, K: string) => void) { |
| 162 | + for (let k of Object.keys(map)) { |
| 163 | + callback(map[k], k); |
| 164 | + } |
| 165 | + } |
| 166 | + |
| 167 | + static merge<V>(m1: {[key: string]: V}, m2: {[key: string]: V}): {[key: string]: V} { |
| 168 | + var m: {[key: string]: V} = {}; |
| 169 | + |
| 170 | + for (let k of Object.keys(m1)) { |
| 171 | + m[k] = m1[k]; |
| 172 | + } |
| 173 | + |
| 174 | + for (let k of Object.keys(m2)) { |
| 175 | + m[k] = m2[k]; |
| 176 | + } |
| 177 | + |
| 178 | + return m; |
| 179 | + } |
| 180 | + |
| 181 | + static equals<V>(m1: {[key: string]: V}, m2: {[key: string]: V}): boolean { |
| 182 | + var k1 = Object.keys(m1); |
| 183 | + var k2 = Object.keys(m2); |
| 184 | + if (k1.length != k2.length) { |
| 185 | + return false; |
| 186 | + } |
| 187 | + var key: any /** TODO #???? */; |
| 188 | + for (var i = 0; i < k1.length; i++) { |
| 189 | + key = k1[i]; |
| 190 | + if (m1[key] !== m2[key]) { |
| 191 | + return false; |
| 192 | + } |
| 193 | + } |
| 194 | + return true; |
| 195 | + } |
| 196 | +} |
0 commit comments