@tevari/helpers
Version:
Collection of various small helpers for javascript and typescript based projects
455 lines (418 loc) • 13.9 kB
text/typescript
import { Function2, Predicate } from "./functions";
import { Optional } from "./optional";
import { stringIsBlank } from "./strings";
/**
* Tests if at least one element of the given array matches the predicate.
*
* @param array The array to test
* @param predicate The predicate used to test each element of the given array
* @returns `true` if at leat one element matches the given predicate, `false` otherwise.
*/
export const arrayMatchOneOrMore = <T>(
array: T[],
predicate: Predicate<T>
): boolean => {
return array.filter((value) => !!value).filter(predicate).length > 0;
};
/**
* Tests if exactly one element of the given array matches the predicate.
*
* @param array The array to test
* @param predicate The predicate used to test each element of the given array
* @returns `true` if one element only matches the given predicate, `false` otherwise.
*/
export const arrayMatchOneExactly = <T>(
array: T[],
predicate: Predicate<T>
): boolean => {
return array.filter((value) => !!value).filter(predicate).length === 1;
};
/**
* Tests if all elements of the given array match the predicate.
*
* @param array The array to test
* @param predicate The predicate used to test each element of the given array
* @returns `true` if all of the elements match the given predicate, `false` otherwise.
*/
export const arrayMatchAll = <T>(
array: T[],
predicate: Predicate<T>
): boolean => {
const cleanedArray = array.filter((value) => !!value);
return (
cleanedArray.length > 0 &&
cleanedArray.filter(predicate).length === cleanedArray.length
);
};
/**
* Tests whether the given arrays are exactly the same in length and content.
* If no predicate is given to compare the elements of the arrays, `===` will be used.
*
* @param array1 The first array to test
* @param array2 The second array to test
* @param comparator The predicate used to compare each element of the given arrays.
* @returns `true` if both arrays are equal, `false` otherwise.
*/
export const arraysAreSame = <T>(
array1: T[],
array2: T[],
comparator?: Function2<T, T, boolean>
): boolean => {
return (
array1.length == array2.length &&
array1.every((element, index) =>
comparator !== undefined
? comparator(element, array2[index])
: element === array2[index]
)
);
};
/**
* Creates an array of the given length composed of a suite of numbers from `offset` to `offset + (length * step)`.
*
* @param length The length of the array to be created.
* @param offset The starting offset of the suite to be created. `1` is set by default.
* @returns the suite array from `offset` to `offset + (length * step)`.
*/
export const arrayCreateSuite = (
length: number,
offset = 1,
step = 1
): number[] => {
return Array.from({ length }, (_, i) => offset + i * step);
};
export const EMPTY_ARRAY = [];
/**
* Strips the given string array of any blank values (either `null`, `undefined` of empty string).
*
* @param array The string array to be cleaned.
* @returns `undefined` if the given array was undefined, the cleaned up array otherwise.
*/
export const arrayCleanStringArray = (
array?: (string | undefined | null)[]
): string[] | undefined => {
if (!array) return;
return array.filter((value) => !stringIsBlank(value)) as string[];
};
/**
* Shuffles the elements of the given array to a random order.
*
* @param array The array to shuffle.
* @returns An array with every elements of the given array but in a random order.
*/
export const arrayShuffle = <T>(array: T[]): T[] => {
let currentIndex: number = array.length;
let temporaryValue: T, randomIndex: number;
while (currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
};
/**
* Strips the given array of duplicate values.
*
* @param array The array with potential duplicates.
* @returns An array where of elements are uniq.
*/
export const arrayUniq = <T>(array: T[]): T[] => {
return array.filter((v, i, a) => a.indexOf(v) === i);
};
/**
* Strips the given array of duplicate property values.
*
* @param array The array with potential duplicates.
* @param property The property to extract for the comparaison.
* @param comparator The predicate used to compare each element of the given arrays.
* @returns An array where of elements are uniq.
*/
export const arrayUniqObjectsByProperty = <T extends { [id: string]: any }>(
array: T[],
property: string,
comparator?: Function2<T, T, boolean>
): T[] => {
return array.filter(
(obj, i) =>
array.findIndex((a) =>
comparator
? comparator(a[property], obj[property])
: a[property] === obj[property]
) === i
);
};
/**
* Extracts the last element from the given array.
*
* @param array The array to extract the last element from.
* @returns the last element.
*/
export const arrayLast = <T>(array: T[]): T | undefined => {
const length = array.length;
if (length === 0) return;
return array[array.length - 1];
};
/**
* Extracts the last element from the given array as an optional.
*
* @param array The array to extract the last element from.
* @returns the last element as an optional.
*/
export const arrayLastOptional = <T>(array: T[]): Optional<T> => {
const length = array.length;
if (length === 0) return Optional.empty();
return Optional.filled(array[array.length - 1]);
};
/**
* Extracts the first element from the given array.
*
* @param array The array to extract the first element from.
* @returns the first element.
*/
export const arrayFirst = <T>(array: T[]): T | undefined => {
if (array.length === 0) return;
return array[0];
};
/**
* Calculate the sum of the extracted values.
*
* @param array The array.
* @param valueExtractor The extractor used to retrieve values to be sum up.
* @returns the total.
*/
export const arraySum = <T>(
array: T[],
valueExtractor?: (item: T) => number
) => {
if (array.length === 0) return 0;
return array
.filter((v) => v !== null && v !== undefined)
.map((value) => valueExtractor ? valueExtractor(value) : Number(value))
.reduce((total, current) => total + current, 0);
};
/**
* Calculate the average of the extracted values.
*
* @param array The array.
* @param valueExtractor The extractor used to retrieve values to be averaged up.
* @returns the average.
*/
export const arrayAverage = <T>(
array: T[],
valueExtractor?: (item: T) => number,
rounded: boolean = true
) => {
if (array.length === 0) return 0;
const total = arraySum(array, valueExtractor);
const average = total / array.length;
const finalAverage = rounded ? Math.round(average) : average;
return finalAverage >= 0 ? finalAverage : 0;
};
/**
* Extracts the first element from the given array as an optional.
*
* @param array The array to extract the first element from.
* @returns the first element as an optional.
*/
export const arrayFirstOptional = <T>(array: T[]): Optional<T> => {
if (array.length === 0) return Optional.empty();
return Optional.filled(array[0]);
};
/**
* Push the given value to the given array only if the value is not already present in the given array.
*
* @param array The array in which to insert the new value.
* @param newValue The new value to insert.
* @param valueComparator The comparator used to compare values from the array.
*/
export const arrayPushNewValue = <T>(
array: T[],
newValue: T,
valueComparator?: (value1: T, value2: T) => boolean
) => {
if (array.length === 0) {
array.push(newValue);
return;
}
if (
!array.find((value) =>
valueComparator ? valueComparator(value, newValue) : value === newValue
)
) {
array.push(newValue);
}
};
/**
* Push the given values to the given array only if the values are not already present in the given array.
* The duplicate values will not be pushed but any other values will be.
*
* @param array The array in which to insert the new value.
* @param newValue The new values to insert.
* @param valueComparator The comparator used to compare values from the array.
*/
export const arrayPushNewValues = <T>(
array: T[],
newValues: T[],
valueComparator?: (value1: T, value2: T) => boolean
) => {
if (array.length === 0) {
array.push(...newValues);
return;
}
for (const newValue of newValues) {
arrayPushNewValue(array, newValue, valueComparator);
}
};
export const ArrayHelpers = {
/**
* Tests if all elements of the given array match the predicate.
*
* @param array The array to test
* @param predicate The predicate used to test each element of the given array
* @returns `true` if all of the elements match the given predicate, `false` otherwise.
*/
matchAll: arrayMatchAll,
/**
* Tests if exactly one element of the given array matches the predicate.
*
* @param array The array to test
* @param predicate The predicate used to test each element of the given array
* @returns `true` if one element only matches the given predicate, `false` otherwise.
*/
matchOneExactly: arrayMatchOneExactly,
/**
* Tests if at least one element of the given array matches the predicate.
*
* @param array The array to test
* @param predicate The predicate used to test each element of the given array
* @returns `true` if at leat one element matches the given predicate, `false` otherwise.
*/
matchOneOrMore: arrayMatchOneOrMore,
/**
* Tests whether the given arrays are exactly the same in length and content.
* If no predicate is given to compare the elements of the arrays, `===` will be used.
*
* @param array1 The first array to test
* @param array2 The second array to test
* @param comparator The predicate used to compare each element of the given arrays.
* @returns `true` if both arrays are equal, `false` otherwise.
*/
same: arraysAreSame,
/**
* Strips the given string array of any blank values (either `null`, `undefined` of empty string).
*
* @param array The string array to be cleaned.
* @returns `undefined` if the given array was undefined, the cleaned up array otherwise.
*/
cleanStringArray: arrayCleanStringArray,
/**
* Creates an array of the given length composed of a suite of numbers from `offset` to `offset + (length * step)`.
*
* @param length The length of the array to be created.
* @param offset The starting offset of the suite to be created. `1` is set by default.
* @returns the suite array from `offset` to `offset + (length * step)`.
*/
createSuite: arrayCreateSuite,
/**
* Shuffles the elements of the given array to a random order.
*
* @param array The array to shuffle.
* @returns An array with every elements of the given array but in a random order.
*/
shuffle: arrayShuffle,
/**
* Strips the given array of duplicate values.
*
* @param array The array with potential duplicates.
* @returns An array where of elements are uniq.
*/
uniq: arrayUniq,
/**
* Strips the given array of duplicate property values.
*
* @param array The array with potential duplicates.
* @param property The property to extract for the comparaison.
* @param comparator The predicate used to compare each element of the given arrays.
* @returns An array where of elements are uniq.
*/
uniqObjectsByProperty: arrayUniqObjectsByProperty,
/**
* Extracts the last element from the given array.
*
* @param array The array to extract the last element from.
* @returns the last element.
*/
last: arrayLast,
/**
* Extracts the last element from the given array as an optional.
*
* @param array The array to extract the last element from.
* @returns the last element as an optional.
*/
lastOptional: arrayLastOptional,
/**
* Extracts the first element from the given array.
*
* @param array The array to extract the first element from.
* @returns the first element.
*/
first: arrayFirst,
/**
* Extracts the first element from the given array as an optional.
*
* @param array The array to extract the first element from.
* @returns the first element as an optional.
*/
firstOptional: arrayFirstOptional,
/**
* Calculate the sum of the extracted values.
*
* @param array The array.
* @param valueExtractor The extractor used to retrieve values to be sum up.
* @returns the total.
*/
sum: arraySum,
/**
* Calculate the average of the extracted values.
*
* @param array The array.
* @param valueExtractor The extractor used to retrieve values to be averaged up.
* @returns the average.
*/
average: arrayAverage,
/**
* Push the given value to the given array only if the value is not already present in the given array.
*
* @param array The array in which to insert the new value.
* @param newValue The new value to insert.
* @param valueComparator The comparator used to compare values from the array.
*/
pushNewValue: arrayPushNewValue,
/**
* Push the given values to the given array only if the values are not already present in the given array.
* The duplicate values will not be pushed but any other values will be.
*
* @param array The array in which to insert the new value.
* @param newValue The new values to insert.
* @param valueComparator The comparator used to compare values from the array.
*/
pushNewValues: arrayPushNewValues,
};
export const ArraySymbols = {
/**
* An empty array.
*/
empty: EMPTY_ARRAY,
};
export const Arrays = {
/**
* Array helper methods.
*/
helper: ArrayHelpers,
/**
* Array symbols.
*/
symbol: ArraySymbols,
};