-
Notifications
You must be signed in to change notification settings - Fork 28
/
XMap.js
153 lines (134 loc) · 4.39 KB
/
XMap.js
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
/**
* Class representing an extended version of the Map class that supports storing more than
* 16,777,215 keys by using multiple Map instances internally. This class provides a unified
* interface to interact with these maps as if it were a single map.
*
* Based on InfinityMap by Fabio Spampinato (https://github.com/fabiospampinato/infinity-map) released under the MIT License.
*/
class XMap {
#pool;
/**
* Creates an instance of XMap.
* @param {Array} [entries=[]] - Initial set of key-value pairs to add to the map.
*/
constructor(entries = []) {
/**
* @private
* @type {Array<Map<any, any>>} - Array of Map instances used to store key-value pairs.
*/
this.#pool = [new Map(entries)];
}
/**
* Gets the total number of key-value pairs across all maps.
* @return {number} The total number of key-value pairs.
*/
get size() {
return this.#pool.reduce((sum, map) => sum + map.size, 0);
}
/**
* Removes all key-value pairs from the XMap.
*/
clear() {
this.#pool = [new Map()];
}
/**
* Deletes a key-value pair from the XMap.
* @param {any} key - The key of the element to remove.
* @return {boolean} True if an element in the XMap existed and has been removed,
* or false if the element does not exist.
*/
delete(key) {
return this.#pool.some(map => map.delete(key));
}
/**
* Returns a specified element from the XMap.
* @param {any} key - The key of the element to return.
* @return {any} The element associated with the specified key, or undefined if the
* key can't be found in the XMap.
*/
get(key) {
for (const map of this.#pool) {
if (map.has(key)) {
return map.get(key);
}
}
}
/**
* Checks whether an element with the specified key exists in the XMap.
* @param {any} key - The key to check for.
* @return {boolean} True if an element with the specified key exists, otherwise false.
*/
has(key) {
return this.#pool.some(map => map.has(key));
}
/**
* Sets the value for the key in the XMap.
* @param {any} key - The key of the element to add.
* @param {any} value - The value of the element to add.
* @return {XMap} The XMap instance, allowing for chaining.
*/
set(key, value) {
let targetMap = this.#pool[0];
if (this.#pool.length > 1) {
for (const map of this.#pool) {
if (map.has(key)) {
targetMap = map;
break;
}
}
}
targetMap.set(key, value);
if (this.#pool[0].size === 16777215) {
this.#pool.unshift(new Map());
}
return this;
}
/**
* Creates an iterator that contains all [key, value] pairs for each element in the XMap in insertion order.
* @return {Iterator} An iterator for the XMap entries.
*/
*[Symbol.iterator]() {
for (const map of this.#pool) {
yield* map;
}
}
/**
* Creates an iterator that contains the keys for each element in the XMap in insertion order.
* @return {Iterator} An iterator for the XMap keys.
*/
*keys() {
for (const map of this.#pool) {
yield* map.keys();
}
}
/**
* Creates an iterator that contains the values for each element in the XMap in insertion order.
* @return {Iterator} An iterator for the XMap values.
*/
*values() {
for (const map of this.#pool) {
yield* map.values();
}
}
/**
* Creates an iterator that contains an array of [key, value] for each element in the XMap in insertion order.
* @return {Iterator} An iterator for the XMap entries.
*/
*entries() {
for (const map of this.#pool) {
yield* map.entries();
}
}
/**
* Executes a provided function once for each XMap element.
* @param {Function} callback - Function to execute for each element, taking three arguments:
* value, key, and the XMap instance.
* @param {any} [thisArg] - Value to use as this when executing callback.
*/
forEach(callback, thisArg) {
for (const [key, value] of this) {
callback.call(thisArg, value, key, this);
}
}
}
module.exports = XMap;