nhb-toolbox
Version:
A versatile collection of smart, efficient, and reusable utility functions and classes for everyday development needs.
162 lines (161 loc) • 6.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createOptionsArray = createOptionsArray;
exports.removeDuplicatesFromArray = removeDuplicatesFromArray;
exports.getDuplicates = getDuplicates;
exports.findMissingElements = findMissingElements;
exports.splitArray = splitArray;
exports.splitArrayByProperty = splitArrayByProperty;
exports.rotateArray = rotateArray;
exports.moveArrayElement = moveArrayElement;
const non_primitives_1 = require("../guards/non-primitives");
const primitives_1 = require("../guards/primitives");
const index_1 = require("../utils/index");
const helpers_1 = require("./helpers");
/**
* * Converts an array of objects into a formatted array of options.
*
* @param data - An array of objects to convert into options.
* @param config - The configuration object to specify the keys for the `value` (firstFieldName) and `label` (secondFieldName) fields and rename as needed.
* @returns An array of options, where each option has `value` and `label` fields as default or as specified by user in the config options.
*/
function createOptionsArray(data, config) {
const { firstFieldKey, secondFieldKey, firstFieldName = 'value', secondFieldName = 'label', retainNumberValue = false, } = config || {};
if (data && data?.length) {
return data?.map((datum) => {
const firstValue = retainNumberValue && (0, primitives_1.isNumber)(datum[firstFieldKey]) ?
datum[firstFieldKey]
: String(datum[firstFieldKey] ?? '');
return {
[firstFieldName]: firstValue,
[secondFieldName]: String(datum[secondFieldKey] ?? ''),
};
});
}
else {
return [];
}
}
/**
* * Removes duplicate values from an array, supporting deep comparison for objects and arrays.
*
* @param array - The array from which duplicates need to be removed.
* @returns A new array with duplicates removed.
*/
function removeDuplicatesFromArray(array) {
return array?.filter((item, index, self) => index === self?.findIndex((el) => (0, index_1.isDeepEqual)(el, item)));
}
/**
* * Finds duplicate values in an array, runs deep comparison for objects and arrays.
*
* @param array - The array in which to find duplicates.
* @returns An array containing all duplicate entries (each one only once).
*/
function getDuplicates(array) {
const seen = [];
const duplicates = [];
for (const item of array) {
const hasSeen = seen?.find((el) => (0, index_1.isDeepEqual)(el, item));
const hasDuplicate = duplicates?.find((el) => (0, index_1.isDeepEqual)(el, item));
if (hasSeen && !hasDuplicate) {
duplicates?.push(item);
}
else if (!hasSeen) {
seen?.push(item);
}
}
return duplicates;
}
/**
* * Finds elements missing from one array compared to another using deep comparison.
*
* @param options - Configuration to specify which array to compare and direction of check.
* @returns An array of missing elements based on the comparison direction.
*/
/**
* * Finds elements missing from one array compared to another using deep comparison.
*
* @param array1 The first array to compare.
* @param array2 The second array to compare.
* @param missingFrom Which direction to compare for missing values:.
* - `'from-first'` → values in `array1` missing in `array2`.
* - `'from-second'` → values in `array2` missing in `array1`.
* @returns An array of missing elements based on the comparison direction.
*/
function findMissingElements(array1, array2, missingFrom) {
const source = (missingFrom === 'from-first' ? array1 : array2) ?? [];
const target = (missingFrom === 'from-first' ? array2 : array1) ?? [];
return source.filter((s) => !target?.some((t) => (0, index_1.isDeepEqual)(t, s)));
}
/**
* * Splits an array into chunks of a given size.
*
* @param arr The array to split.
* @param chunkSize The size of each chunk.
* @returns An array of chunked arrays.
*/
function splitArray(arr, chunkSize) {
const result = [];
for (let i = 0; i < arr?.length; i += chunkSize) {
result.push(arr.slice(i, i + chunkSize));
}
return result;
}
/**
* * Group an array of objects by a specified key, returning only arrays of grouped objects.
*
* @param source - The source array of objects to group.
* @param property - The property to group the array by. Property can be a string, number, boolean, undefined or null. Supports nested dot notation.
*
* @returns An array of grouped arrays. Each sub-array contains objects that share the same value for the specified property.
*
* @example
* splitArrayByProperty([{ type: 'a' }, { type: 'b' }, { type: 'a' }, { type: undefined }], 'type')
* // => [ [{ type: 'a' }, { type: 'a' }], [{ type: 'b' }], [{ type: undefined }] ]
*
* @notes
* - Returns an empty array if the input is invalid or empty.
* - Groups objects even when the group key is `undefined` or `null` (object with `null` & `undefined` property-values are grouped together).
*/
function splitArrayByProperty(source, property) {
if (!(0, non_primitives_1.isValidArray)(source))
return [];
const grouped = {};
source.forEach((item) => {
const rawKey = (0, helpers_1._resolveNestedKey)(item, property);
const key = rawKey != null ? String(rawKey) : '__undefined__';
if (!grouped[key]) {
grouped[key] = [];
}
grouped[key].push(item);
});
return Object.values(grouped);
}
/**
* * Rotates an array left or right by a given number of steps.
*
* @param arr The array to rotate.
* @param steps The number of positions to rotate (positive: right, negative: left).
* @returns The rotated array.
*/
function rotateArray(arr, steps) {
const length = arr?.length;
if (length === 0)
return arr;
const offset = ((steps % length) + length) % length;
return arr.slice(-offset).concat(arr.slice(0, -offset));
}
/**
* * Moves an element within an array from one index to another.
*
* @param arr The array to modify.
* @param fromIndex The index of the element to move.
* @param toIndex The new index for the element.
* @returns A new array with the element moved.
*/
function moveArrayElement(arr, fromIndex, toIndex) {
const newArr = [...arr];
const [item] = newArr.splice(fromIndex, 1);
newArr.splice(toIndex, 0, item);
return newArr;
}