@techmely/utils
Version:
Collection of helpful JavaScript / TypeScript utils
146 lines (142 loc) • 4.05 kB
JavaScript
/*!
* @techmely/utils
* Copyright(c) 2021-2024 Techmely <techmely.creation@gmail.com>
* MIT Licensed
*/
// src/orderMap.ts
var OrderedMap = class _OrderedMap {
constructor(content) {
this.content = content;
}
// Return a map with the given content. If null, create an empty
// map. If given an ordered map, return that map itself. If given an
// object, create a map from the object's properties.
static from(value) {
if (value instanceof _OrderedMap)
return value;
const content = [];
if (value)
for (const prop in value)
content.push(prop, value[prop]);
return new _OrderedMap(content);
}
/**
* the amount of keys in this map.
*/
get size() {
return this.content.length >> 1;
}
#find(key) {
for (let i = 0; i < this.content.length; i += 2)
if (this.content[i] === key)
return i;
return -1;
}
/**
* Retrieve the value stored under `key`, or return undefined when no such key exists.
*/
get(key) {
const found = this.#find(key);
return found === -1 ? void 0 : this.content[found + 1];
}
/**
* Create a new map by replacing the value of `key` with a new value,
* or adding a binding to the end of the map. If `newKey` is given, the key of the binding will be replaced with that key.
*/
update(key, value, newKey) {
const self = newKey && newKey !== key ? this.remove(newKey) : this;
const found = self.#find(key);
const content = self.content.slice();
if (found === -1) {
content.push(newKey || key, value);
} else {
content[found + 1] = value;
if (newKey)
content[found] = newKey;
}
return new _OrderedMap(content);
}
/**
* Return a map with the given key removed, if it existed.
*/
remove(key) {
const found = this.#find(key);
if (found === -1)
return this;
const content = this.content.slice();
content.splice(found, 2);
return new _OrderedMap(content);
}
/**
* Add a new key to the start of the map.
*/
addToStart(key, value) {
return new _OrderedMap([key, value].concat(this.remove(key).content));
}
/**
* Add a new key to the end of the map.
*/
addToEnd(key, value) {
const content = this.remove(key).content.slice();
content.push(key, value);
return new _OrderedMap(content);
}
/**
* Add the given key/value before `place`. If `place` is not found, the new key is added to the end.
*/
addBefore(place, key, value) {
const without = this.remove(key);
const content = without.content.slice();
const found = without.#find(place);
content.splice(found === -1 ? content.length : found, 0, key, value);
return new _OrderedMap(content);
}
/**
* Call the given function for each key/value pair in the map, in order
*/
forEach(fn) {
for (let i = 0; i < this.content.length; i += 2) {
fn(this.content[i], this.content[i + 1]);
}
}
/**
* Create a new map by prepending the keys in this map that don't appear in `map` before the keys in `map`
*/
prepend(map) {
map = _OrderedMap.from(map);
if (!map.size)
return this;
return new _OrderedMap(map.content.concat(this.subtract(map).content));
}
/**
* Create a new map by appending the keys in this map that don't appear in `map` after the keys in `map`.
*/
append(map) {
map = _OrderedMap.from(map);
if (!map.size)
return this;
return new _OrderedMap(this.subtract(map).content.concat(map.content));
}
/**
* Create a map containing all the keys in this map that don't appear in `map`
*/
subtract(map) {
let instance = this;
map = _OrderedMap.from(map);
for (let i = 0; i < map.content.length; i += 2) {
instance = instance.remove(map.content[i]);
}
return instance;
}
/**
* Turn ordered map into a plain object.
*/
toObject() {
const result = {};
this.forEach((key, value) => {
result[key] = value;
});
return result;
}
};
export { OrderedMap };