288 lines
6.5 KiB
TypeScript
288 lines
6.5 KiB
TypeScript
/**
|
|
* @author Martin Karkowski
|
|
* @email m.karkowski@zema.de
|
|
*/
|
|
|
|
import { rgetattr } from "./objectMethods";
|
|
|
|
/**
|
|
* Sorts a List based on the given property
|
|
* Usage :
|
|
* a = [{a : 1, b: 2}, {a : 2, b: 1}];
|
|
* b = a.sort(dynamicSort('b'))
|
|
* b => [{a : 2, b: 1}, {a : 1, b: 2}]
|
|
*
|
|
* @export
|
|
* @param {string} _property Property Name / Path to Sort the List
|
|
* @returns
|
|
*/
|
|
export function dynamicSort(_property: string, reverse = false): any {
|
|
const _sortOrder = reverse ? -1 : 1;
|
|
|
|
return function (a, b) {
|
|
const _a = rgetattr(a, _property);
|
|
const _b = rgetattr(b, _property);
|
|
if (typeof _a === "number" && typeof _b === "number") {
|
|
const result = _a < _b ? -1 : _a > _b ? 1 : 0;
|
|
return result * _sortOrder;
|
|
} else if (typeof _a === "number") {
|
|
return 1 * _sortOrder;
|
|
} else if (typeof _b === "number") {
|
|
return -1 * _sortOrder;
|
|
} else if (typeof _a === "string" && typeof _b === "string") {
|
|
return _a < _b ? -1 : _a > _b ? 1 : 0;
|
|
}
|
|
|
|
return 0;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Extracts the Data of the given List
|
|
* @export
|
|
* @param {Array<any>} list List, where data should be extracted
|
|
* @param {string} path path pointing to the Data in the List
|
|
* @returns {Array<any>} List only containing the Elements.
|
|
*/
|
|
export function extractListElement(list: Array<any>, path: string): Array<any> {
|
|
// Define Function to extract the Properties.
|
|
function _extract(_property) {
|
|
const _ret = rgetattr(_property, path);
|
|
/** Returns the Value if it is in the Element */
|
|
if (_ret) {
|
|
return _ret;
|
|
}
|
|
}
|
|
|
|
return list.map(_extract);
|
|
}
|
|
|
|
/**
|
|
* Converts a List to Set
|
|
*
|
|
* @export
|
|
* @template T
|
|
* @param {Array<T>} list
|
|
* @returns {Set<T>}
|
|
*/
|
|
export function toSet<T>(list: Array<T>): Set<T> {
|
|
const _ret = new Set<T>();
|
|
|
|
for (const item of list) {
|
|
_ret.add(item);
|
|
}
|
|
|
|
return _ret;
|
|
}
|
|
|
|
/**
|
|
* Extracts the first Element if Possible, which includes the Operand
|
|
*
|
|
* const a = [{path:'hallo'}, {path:'hallo2'}]
|
|
*
|
|
* getElement(a, 'hallo2', 'path')
|
|
*
|
|
* @export
|
|
* @template T
|
|
* @param {Array<T>} list The list which is considered
|
|
* @param {*} operand The Element which should looked for
|
|
* @param {string} [path=''] The where the Element should be found
|
|
* @returns {(T | null)}
|
|
*/
|
|
export function getElement<T>(
|
|
list: Array<T>,
|
|
operand: any,
|
|
path = ""
|
|
): T | null {
|
|
/** Iterate through the List an get the requested Element if possible */
|
|
for (const _element of list) {
|
|
/** Compare the Requested value with the value of the List-Item */
|
|
if (operand === rgetattr(_element, path)) {
|
|
return _element;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Function that will compare two arrays, if they are equal.
|
|
* @param a Array Element A
|
|
* @param b Array Element B
|
|
* @param considerOrder Flag to enable/disable Order checking
|
|
*/
|
|
export function arraysEqual(
|
|
a: Array<any>,
|
|
b: Array<any>,
|
|
considerOrder = true
|
|
): boolean {
|
|
if (a === b) return true;
|
|
if (a == null || b == null) return false;
|
|
if (a.length != b.length) return false;
|
|
|
|
let _a = a;
|
|
let _b = b;
|
|
|
|
if (!considerOrder) {
|
|
_a = a.concat().sort();
|
|
_b = b.concat().sort();
|
|
}
|
|
|
|
for (let i = 0; i < _a.length; ++i) {
|
|
if (_a[i] !== _b[i]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Function which will limit the Amount of Element stored in the Array during
|
|
* pushing a new Element. If the Maximum is exited the Elementes will be removed
|
|
* with the FIFO Principal.
|
|
* @param array The considered Array
|
|
* @param element The Element which should be added
|
|
* @param maxElements The Max. Amount of Elements, which are allowed to store.
|
|
*/
|
|
export function limitedPush<T>(
|
|
array: T[],
|
|
element: T,
|
|
maxElements: number
|
|
): void {
|
|
array.push(element);
|
|
|
|
if (array.length > maxElements) {
|
|
array.splice(0, 1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to count the Number of Element in an Array. A Dict with the Elements
|
|
* as string will be returned.
|
|
* @param array The Array
|
|
*/
|
|
export function countElements<T>(array: Array<T>): Map<T, number> {
|
|
const ret: Map<T, number> = new Map();
|
|
|
|
for (const element of array) {
|
|
ret.set(element, (ret.get(element) || 0) + 1);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Function, which will Flatten the Array.
|
|
* @param arrayToFlatten The Array
|
|
*/
|
|
export function flattenDeep<T>(arrayToFlatten) {
|
|
return arrayToFlatten.reduce((acc, val) => {
|
|
return Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val);
|
|
}, []) as T[];
|
|
}
|
|
|
|
/**
|
|
* Function, to Test whether the Element is present in the Array
|
|
* @param objToTest The Object to Test
|
|
* @param array The array to consider
|
|
* @param path The path, under which the element will be found
|
|
*/
|
|
export function elementInArray<T>(objToTest: T, array: Array<T>, path: string) {
|
|
const testData = rgetattr(objToTest, path, false);
|
|
for (const [idx, element] of array.entries()) {
|
|
if (testData === rgetattr(element, path, true)) {
|
|
return idx;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Function to ZIP to Arrays.
|
|
* @param arr1
|
|
* @param arr2
|
|
*/
|
|
export function zipArrays<T, K>(arr1: T[], arr2: K[]): Array<[T, K]> {
|
|
if (arr1.length !== arr2.length) {
|
|
throw Error("Length of the Elements doesnt match!");
|
|
}
|
|
|
|
const res: Array<[T, K]> = arr1.map(function (e, i) {
|
|
return [e, arr2[i]];
|
|
});
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Helper to determine the average of an array
|
|
*
|
|
* @author M.Karkowski
|
|
* @export
|
|
* @param {any[]} arr
|
|
* @param {string} path
|
|
* @param {number} [defaultValue=0]
|
|
* @return {*} {number}
|
|
*/
|
|
export function avgOfArray(arr: any[], path: string, defaultValue = 0): number {
|
|
if (arr.length === 0) {
|
|
return defaultValue;
|
|
}
|
|
|
|
const arrOfValues = arr.map((item) => {
|
|
return rgetattr(item, path, defaultValue);
|
|
});
|
|
const added = arrOfValues.reduce((prev, curr) => {
|
|
return prev + curr;
|
|
}) as number;
|
|
return added / arr.length;
|
|
}
|
|
|
|
export function minOfArray<T>(
|
|
arr: T[],
|
|
path: keyof T | string,
|
|
defaultValue = 0
|
|
): {
|
|
min: number;
|
|
index: number;
|
|
} {
|
|
if (arr.length === 0) {
|
|
return {
|
|
min: defaultValue,
|
|
index: -1,
|
|
};
|
|
}
|
|
|
|
const arrOfValues = arr.map((item) => {
|
|
return rgetattr<number>(item, path as string, defaultValue);
|
|
});
|
|
const min = Math.min(...arrOfValues);
|
|
return {
|
|
min,
|
|
index: arrOfValues.indexOf(min),
|
|
};
|
|
}
|
|
|
|
export function maxOfArray(
|
|
arr: any[],
|
|
path: string,
|
|
defaultValue = 0
|
|
): {
|
|
max: number;
|
|
index: number;
|
|
} {
|
|
if (arr.length === 0) {
|
|
return {
|
|
max: defaultValue,
|
|
index: -1,
|
|
};
|
|
}
|
|
|
|
const arrOfValues = arr.map((item) => {
|
|
return rgetattr<number>(item, path, defaultValue);
|
|
});
|
|
const max = Math.max(...arrOfValues);
|
|
return {
|
|
max: max,
|
|
index: arrOfValues.indexOf(max),
|
|
};
|
|
}
|