stringDictionary.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /**
  2. * This class implement a typical dictionary using a string as key and the generic type T as value.
  3. * The underlying implementation relies on an associative array to ensure the best performances.
  4. * The value can be anything including 'null' but except 'undefined'
  5. */
  6. export class StringDictionary {
  7. constructor() {
  8. this._count = 0;
  9. this._data = {};
  10. }
  11. /**
  12. * This will clear this dictionary and copy the content from the 'source' one.
  13. * If the T value is a custom object, it won't be copied/cloned, the same object will be used
  14. * @param source the dictionary to take the content from and copy to this dictionary
  15. */
  16. copyFrom(source) {
  17. this.clear();
  18. source.forEach((t, v) => this.add(t, v));
  19. }
  20. /**
  21. * Get a value based from its key
  22. * @param key the given key to get the matching value from
  23. * @returns the value if found, otherwise undefined is returned
  24. */
  25. get(key) {
  26. const val = this._data[key];
  27. if (val !== undefined) {
  28. return val;
  29. }
  30. return undefined;
  31. }
  32. /**
  33. * Get a value from its key or add it if it doesn't exist.
  34. * This method will ensure you that a given key/data will be present in the dictionary.
  35. * @param key the given key to get the matching value from
  36. * @param factory the factory that will create the value if the key is not present in the dictionary.
  37. * The factory will only be invoked if there's no data for the given key.
  38. * @returns the value corresponding to the key.
  39. */
  40. getOrAddWithFactory(key, factory) {
  41. let val = this.get(key);
  42. if (val !== undefined) {
  43. return val;
  44. }
  45. val = factory(key);
  46. if (val) {
  47. this.add(key, val);
  48. }
  49. return val;
  50. }
  51. /**
  52. * Get a value from its key if present in the dictionary otherwise add it
  53. * @param key the key to get the value from
  54. * @param val if there's no such key/value pair in the dictionary add it with this value
  55. * @returns the value corresponding to the key
  56. */
  57. getOrAdd(key, val) {
  58. const curVal = this.get(key);
  59. if (curVal !== undefined) {
  60. return curVal;
  61. }
  62. this.add(key, val);
  63. return val;
  64. }
  65. /**
  66. * Check if there's a given key in the dictionary
  67. * @param key the key to check for
  68. * @returns true if the key is present, false otherwise
  69. */
  70. contains(key) {
  71. return this._data[key] !== undefined;
  72. }
  73. /**
  74. * Add a new key and its corresponding value
  75. * @param key the key to add
  76. * @param value the value corresponding to the key
  77. * @returns true if the operation completed successfully, false if we couldn't insert the key/value because there was already this key in the dictionary
  78. */
  79. add(key, value) {
  80. if (this._data[key] !== undefined) {
  81. return false;
  82. }
  83. this._data[key] = value;
  84. ++this._count;
  85. return true;
  86. }
  87. /**
  88. * Update a specific value associated to a key
  89. * @param key defines the key to use
  90. * @param value defines the value to store
  91. * @returns true if the value was updated (or false if the key was not found)
  92. */
  93. set(key, value) {
  94. if (this._data[key] === undefined) {
  95. return false;
  96. }
  97. this._data[key] = value;
  98. return true;
  99. }
  100. /**
  101. * Get the element of the given key and remove it from the dictionary
  102. * @param key defines the key to search
  103. * @returns the value associated with the key or null if not found
  104. */
  105. getAndRemove(key) {
  106. const val = this.get(key);
  107. if (val !== undefined) {
  108. delete this._data[key];
  109. --this._count;
  110. return val;
  111. }
  112. return null;
  113. }
  114. /**
  115. * Remove a key/value from the dictionary.
  116. * @param key the key to remove
  117. * @returns true if the item was successfully deleted, false if no item with such key exist in the dictionary
  118. */
  119. remove(key) {
  120. if (this.contains(key)) {
  121. delete this._data[key];
  122. --this._count;
  123. return true;
  124. }
  125. return false;
  126. }
  127. /**
  128. * Clear the whole content of the dictionary
  129. */
  130. clear() {
  131. this._data = {};
  132. this._count = 0;
  133. }
  134. /**
  135. * Gets the current count
  136. */
  137. get count() {
  138. return this._count;
  139. }
  140. /**
  141. * Execute a callback on each key/val of the dictionary.
  142. * Note that you can remove any element in this dictionary in the callback implementation
  143. * @param callback the callback to execute on a given key/value pair
  144. */
  145. forEach(callback) {
  146. for (const cur in this._data) {
  147. const val = this._data[cur];
  148. callback(cur, val);
  149. }
  150. }
  151. /**
  152. * Execute a callback on every occurrence of the dictionary until it returns a valid TRes object.
  153. * If the callback returns null or undefined the method will iterate to the next key/value pair
  154. * Note that you can remove any element in this dictionary in the callback implementation
  155. * @param callback the callback to execute, if it return a valid T instanced object the enumeration will stop and the object will be returned
  156. * @returns the first item
  157. */
  158. first(callback) {
  159. for (const cur in this._data) {
  160. const val = this._data[cur];
  161. const res = callback(cur, val);
  162. if (res) {
  163. return res;
  164. }
  165. }
  166. return null;
  167. }
  168. }
  169. //# sourceMappingURL=stringDictionary.js.map