//eslint-disable-next-line no-unused-vars
const { Out } = require("./Out"); //lgtm [js/unused-local-variable] JSDoc Type Def
/**.
* Create a Dictionary Object.
*
* {@link #out Out} Type can be replaced with [] in a var
*
* @class Dictionary
* @template T, A
*/
class Dictionary extends Array {
constructor() {
super();
}
/**
* Add an entry to the Dictionary.
*
* Will Error if Key already exists.
*
* @param {T} Key - Value.
* @param {A} Value - Value.
* @memberof Dictionary
* @instance
*/
Add(Key, Value) {
if (this.ContainsKey(Key))
throw new Error(
"ArgumentException: An element with the same key already exists"
);
this.push({
Key,
Value,
});
}
/**.
* Attempt to add an entry to the Dictionary
*
* @param {T} Key
* @param {A} Value
* @memberof Dictionary
* @instance
* @returns {Boolean} - Was the Add command successfull
*/
TryAdd(Key, Value) {
if (this.ContainsKey(Key)) return false;
this.push({
Key,
Value,
});
return true;
}
/**.
* Replace Key's value with new Value
*
* @param {T} key
* @param {A} Value
* @instance
* @memberof Dictionary
* @returns {boolean} - Was replace successful
*/
Replace(key, Value) {
if (!this.ContainsKey(key)) return false;
for (let object of this) {
if (object.Key === key) {
this[this.indexOf(object)].Value = Value;
return true;
}
}
return false;
}
/**.
* Clear the Dictionary
*
* @instance
* @memberof Dictionary
*/
Clear() {
this.splice(0, this.length);
}
CheckCount(func) {
if (func == null) return this.length;
return this.filter(func).length;
}
/**.
* Check if a Key exists
*
* @param {T} Key
* @instance
* @memberof Dictionary
* @returns {boolean} - Key Found
*/
ContainsKey(Key) {
for (let object of this) {
if (object.Key === Key) return true;
}
return false;
}
/**.
* Check if a Value exists in the Dictionary
*
* @param {A} Value
* @instance
* @memberof Dictionary
* @returns {boolean} - Value Exists
*/
ContainsValue(Value) {
for (let object of this) {
if (object.Value === Value) return true;
}
return false;
}
/**.
* Get the Capacity
*
* @deprecated
* @instance
* @memberof Dictionary
*/
EnsureCapacity() {
return this.length;
}
/**.
* Remove an Item at a given Index
*
* @param {number} iIndex
* @instance
* @memberof Dictionary
*/
RemoveAt(iIndex) {
var vItem = this[iIndex];
if (vItem) {
this.splice(iIndex, 1);
}
return vItem;
}
/**.
* Remove a Key. Will error if Key does not exist
*
* @param {T} key
* @instance
* @memberof Dictionary
* @returns {boolean} - Key Removed
*/
Remove(key) {
if (!this.ContainsKey(key)) return false;
for (let object of this) {
if (object.Key === key) {
this.RemoveAt(this.indexOf(object));
return true;
}
}
return false;
}
/**
* Attempt to remove a Key.
*
* @memberof Dictionary
* @instance
* @param {T} key
* @returns {boolean} - Key Removed.
*/
TryRemove(key) {
if (!this.ContainsKey(key)) return false;
for (let object of this) {
if (object.Key === key) {
this.RemoveAt(this.indexOf(object));
return true;
}
}
return false;
}
/**.
* Get the amount of items
*
* @instance
* @readonly
* @memberof Dictionary
*/
get Count() {
return this.length;
}
/**.
* Get a key's value
*
* @param {T} key - Key
* @param {Out<A>} out - Output Var
* @returns {boolean} - Key Exists
*/
Get(key, out) {
if (!this.ContainsKey(key)) return false;
for (let object of this) {
if (object.Key === key) {
out.Out = object.Value;
return true;
}
}
return false; // How tf you manage that??
}
/**.
* Generate a Dictionary from an Object using Key:Value Pairs
*
* @param {Object} obj
*/
static ToDictionary(obj) {
let Dict = new Dictionary();
for (let key in obj) {
Dict.Add(key, obj[key]);
}
return Dict;
}
/**.
* Reduce Callback
*
* @callback Dictionary.Reduce~callback
* @param {*} [previousValue]
* @param {*} [currentValue]
* @param {number} [currentIndex]
* @param {any[]} [array]
* @returns {*} Returned Value will set to set previousValue
*/
/**.
* Reduce a Dictionary's values down
*
* @param {Dictionary.Reduce~callback} callbackfn - Computation function
* @param {*} InitialValue - Initial Value
* @returns {*}
* @instance
* @memberof Dictionary
*/
Reduce(callbackfn, InitialValue) {
if (this.length === 0) return 0;
return this.reduce(callbackfn, InitialValue);
}
/**
* @callback Dictionary.AddOrUpdate~callback
* @param {T} Key - Current Key.
* @param {A} Value - Current Value.
* @returns {A} New Value.
*/
/**.
* Adds a new Value at Key.
*
* If Key exists, Updates Key.
*
* If func is set, Programatically updates Key
*
* @param {T} key
* @param {A} value
* @param {Dictionary.AddOrUpdate~callback} [func]
* @returns {Boolean} Added
* @instance
* @memberof Dictionary
*/
AddOrUpdate(key, value, func) {
if (!this.ContainsKey(key)) {
if (this.TryAdd(key, value)) return value;
return false;
}
if (func == null) {
if (this.Replace(key, value)) return value;
return false;
}
let oldValue = new Out();
this.Get(key, oldValue);
let newValue = func(key, oldValue.Out);
if (this.Replace(key, newValue)) return newValue;
}
/**.
* Attempt to get Value, Sets Value to Out. Returns Boolean valueExists
*
* @param {A} value
* @param {Out<A>} out
* @returns {boolean} - Value Existed
*/
TryGetValue(value, out) {
if (value == null) return false;
if (!this.ContainsKey(value)) return false;
if (out) this.Get(value, out);
return true;
}
GetEnumerator() {
return new (require("./Enumerator").Enumerator)(this);
}
}
module.exports = {
Dictionary,
};