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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
/*-
* ============LICENSE_START=======================================================
* SDC
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============LICENSE_END=========================================================
*/
/**
This code was copy from collections.ts lib
https://github.com/basarat/typescript-collections
**/
'use strict';
// Used internally by dictionary
interface IDictionaryPair<K, V> {
key:K;
value:V;
}
export class Dictionary<K, V> {
/**
* Object holding the key-value pairs.
* @type {Object}
* @private
*/
private table:{ [key:string]:IDictionaryPair<K, V> };
//: [key: K] will not work since indices can only by strings in javascript and typescript enforces this.
/**
* Number of elements in the list.
* @type {number}
* @private
*/
private nElements:number;
/**
* Function used to convert keys to strings.
* @type {function(Object):string}
* @private
*/
private toStr:(key:K) => string;
/**
* Creates an empty dictionary.
* @class <p>Dictionaries map keys to values; each key can map to at most one value.
* This implementation accepts any kind of objects as keys.</p>
*
* <p>If the keys are custom objects a function which converts keys to unique
* strings must be provided. Example:</p>
* <pre>
* function petToString(pet) {
* return pet.name;
* }
* </pre>
* @constructor
* @param {function(Object):string=} toStrFunction optional function used
* to convert keys to strings. If the keys aren"t strings or if toString()
* is not appropriate, a custom function which receives a key and returns a
* unique string must be provided.
*/
constructor(toStrFunction?:(key:K) => string) {
this.table = {};
this.nElements = 0;
this.toStr = toStrFunction || this.defaultToString;
}
/**
copy from angular.js isUndefined
*/
private isUndefined = (value:any):boolean => {
return typeof value === 'undefined';
}
defaultToString = (item:any):string => {
return item.toString();
}
/**
* Returns the value to which this dictionary maps the specified key.
* Returns undefined if this dictionary contains no mapping for this key.
* @param {Object} key key whose associated value is to be returned.
* @return {*} the value to which this dictionary maps the specified key or
* undefined if the map contains no mapping for this key.
*/
getValue = (key:K):V => {
let pair:IDictionaryPair<K, V> = this.table[this.toStr(key)];
if (this.isUndefined(pair)) {
return undefined;
}
return pair.value;
}
/**
* Associates the specified value with the specified key in this dictionary.
* If the dictionary previously contained a mapping for this key, the old
* value is replaced by the specified value.
* @param {Object} key key with which the specified value is to be
* associated.
* @param {Object} value value to be associated with the specified key.
* @return {*} previous value associated with the specified key, or undefined if
* there was no mapping for the key or if the key/value are undefined.
*/
setValue = (key:K, value:V):V => {
if (this.isUndefined(key) || this.isUndefined(value)) {
return undefined;
}
let ret:V;
let k = this.toStr(key);
let previousElement:IDictionaryPair<K, V> = this.table[k];
if (this.isUndefined(previousElement)) {
this.nElements++;
ret = undefined;
} else {
ret = previousElement.value;
}
this.table[k] = {
key: key,
value: value
};
return ret;
}
/**
* Removes the mapping for this key from this dictionary if it is present.
* @param {Object} key key whose mapping is to be removed from the
* dictionary.
* @return {*} previous value associated with specified key, or undefined if
* there was no mapping for key.
*/
remove = (key:K):V => {
let k = this.toStr(key);
let previousElement:IDictionaryPair<K, V> = this.table[k];
if (!this.isUndefined(previousElement)) {
delete this.table[k];
this.nElements--;
return previousElement.value;
}
return undefined;
}
/**
* Returns an array containing all of the keys in this dictionary.
* @return {Array} an array containing all of the keys in this dictionary.
*/
keys = ():K[] => {
let array:K[] = [];
for (let name in this.table) {
if (this.table.hasOwnProperty(name)) {
let pair:IDictionaryPair<K, V> = this.table[name];
array.push(pair.key);
}
}
return array;
}
/**
* Returns an array containing all of the values in this dictionary.
* @return {Array} an array containing all of the values in this dictionary.
*/
values = ():V[] => {
let array:V[] = [];
for (let name in this.table) {
if (this.table.hasOwnProperty(name)) {
let pair:IDictionaryPair<K, V> = this.table[name];
array.push(pair.value);
}
}
return array;
}
/**
* Executes the provided function once for each key-value pair
* present in this dictionary.
* @param {function(Object,Object):*} callback function to execute, it is
* invoked with two arguments: key and value. To break the iteration you can
* optionally return false.
*/
forEach = (callback:(key:K, value:V) => any):void => {
for (let name in this.table) {
if (this.table.hasOwnProperty(name)) {
let pair:IDictionaryPair<K, V> = this.table[name];
let ret = callback(pair.key, pair.value);
if (ret === false) {
return;
}
}
}
}
/**
* Returns true if this dictionary contains a mapping for the specified key.
* @param {Object} key key whose presence in this dictionary is to be
* tested.
* @return {boolean} true if this dictionary contains a mapping for the
* specified key.
*/
containsKey = (key:K):boolean => {
return !this.isUndefined(this.getValue(key));
}
/**
* Removes all mappings from this dictionary.
* @this {Dictionary}
*/
clear = () => {
this.table = {};
this.nElements = 0;
}
/**
* Returns the number of keys in this dictionary.
* @return {number} the number of key-value mappings in this dictionary.
*/
size = ():number => {
return this.nElements;
}
/**
* Returns true if this dictionary contains no mappings.
* @return {boolean} true if this dictionary contains no mappings.
*/
isEmpty = ():boolean => {
return this.nElements <= 0;
}
toString = ():string => {
let toret = "{";
this.forEach((k, v) => {
toret = toret + "\n\t" + k.toString() + " : " + v.toString();
});
return toret + "\n}";
}
} // End of dictionary
|