ts-array-utilities
Version:
multiple array utils, filters, shuffle, sort, etc
433 lines (432 loc) • 13.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.deepSearch = exports.countBy = exports.range = exports.repeat = exports.pad = exports.merge = exports.insert = exports.remove = exports.findLast = exports.findFirst = exports.reverseFill = exports.fill = exports.move = exports.swap = exports.isEqual = exports.isSorted = exports.mirror = exports.flip = exports.rotate = exports.unzip = exports.zip = exports.countOccurrences = exports.standardDeviation = exports.variance = exports.mode = exports.median = exports.mean = exports.randomSample = exports.chunk = exports.removeDuplicates = exports.difference = exports.intersection = exports.partition = exports.groupBy = exports.uniqueElements = exports.flatten = exports.shuffle = exports.distinct = exports.average = exports.sum = exports.max = exports.min = exports.includes = exports.transform = exports.filter = exports.sort = void 0;
const helpers_1 = require("./helpers");
const sorting_algorithms_1 = require("./sorting-algorithms");
const sort = (array, direction = 'asc', sortBy = '') => {
let results = array;
const isNumberArray = typeof array[0] === 'number';
const isStringArray = typeof array[0] === 'string';
if (array.length > 1000) {
results = (0, sorting_algorithms_1.quicksort)(array, sortBy);
}
else {
results = (0, sorting_algorithms_1.insertionSort)(array, sortBy);
}
if (isNumberArray) {
return (0, helpers_1.sortNumberArray)(results, direction);
}
else if (isStringArray) {
return (0, helpers_1.sortStringArray)(results, direction);
}
else {
return (0, helpers_1.sortObjectArray)(results, direction, sortBy);
}
};
exports.sort = sort;
const filter = (array, predicate) => {
const result = [];
for (let i = 0; i < array.length; i++) {
const item = array[i];
if (predicate(item)) {
result.push(item);
}
}
return result;
};
exports.filter = filter;
const transform = (array, transformer = (x) => x) => {
return array.map((x) => {
if (typeof x === 'number') {
return transformer(x);
}
else {
return x;
}
});
};
exports.transform = transform;
const includes = (arr, element) => {
for (const el of arr) {
if (Array.isArray(el)) {
const result = includes(el, element);
if (result !== undefined) {
return result;
}
}
else if ((0, helpers_1.deepEqual)(el, element)) {
return el;
}
}
return undefined;
};
exports.includes = includes;
const min = (array, key) => {
if (!array.length)
return undefined;
if (key) {
return array.reduce((acc, cur) => (cur[key] < acc[key] ? cur : acc));
}
else {
return Math.min(...array);
}
};
exports.min = min;
const max = (array, key) => {
if (!array.length)
return undefined;
if (key) {
return array.reduce((acc, cur) => (cur[key] > acc[key] ? cur : acc));
}
else {
return Math.max(...array);
}
};
exports.max = max;
const sum = (array) => {
return array.reduce((acc, cur) => {
switch (true) {
case typeof cur === 'number':
return acc + cur;
case Array.isArray(cur):
return acc + sum(cur);
case typeof cur === 'object' && 'value' in cur:
return acc + cur.value;
case typeof cur === 'string' && !isNaN(Number(cur)):
return acc + Number(cur);
default:
return acc;
}
}, 0);
};
exports.sum = sum;
const average = (obj) => {
let sum = 0;
let count = 0;
for (const value of Object.values(obj)) {
if ((0, helpers_1.isNumber)(value)) {
sum += value;
count++;
}
else if (typeof value === 'string' && !isNaN(Number(value))) {
sum += Number(value);
count++;
}
else if ((0, helpers_1.isObject)(value)) {
const avg = average(value);
sum += avg * Object.keys(value).length;
count += Object.keys(value).length;
}
}
return count ? sum / count : 0;
};
exports.average = average;
const distinct = (array) => {
if (!Array.isArray(array))
return [];
if (array.every((x) => typeof x === 'object')) {
return [...new Set(array.map((x) => JSON.stringify(x)))].map((x) => JSON.parse(x));
}
if (array.some((x) => Array.isArray(x))) {
return [...new Set(array.flat())];
}
return [...new Set(array)];
};
exports.distinct = distinct;
const shuffle = (array) => {
const copy = [...array];
for (let i = copy.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[copy[i], copy[j]] = [copy[j], copy[i]];
}
return copy;
};
exports.shuffle = shuffle;
const flatten = (array) => {
return array.reduce((flat, next) => flat.concat(Array.isArray(next) ? flatten(next) : next), []);
};
exports.flatten = flatten;
const uniqueElements = (array) => {
return Array.from(new Set(array));
};
exports.uniqueElements = uniqueElements;
const groupBy = (array, callback) => {
return array.reduce((groups, element) => {
const key = callback(element);
groups[key] = groups[key] || [];
groups[key].push(element);
return groups;
}, {});
};
exports.groupBy = groupBy;
const partition = (array, callback) => {
return array.reduce((partitions, element) => {
partitions[callback(element) ? 0 : 1].push(element);
return partitions;
}, [[], []]);
};
exports.partition = partition;
const intersection = (array1, array2) => {
return array1.filter((element) => array2.includes(element));
};
exports.intersection = intersection;
const difference = (array1, array2) => {
return array1.filter((element) => !array2.includes(element));
};
exports.difference = difference;
const removeDuplicates = (array) => {
for (let i = 0; i < array.length; i++) {
for (let j = i + 1; j < array.length; j++) {
if (array[i] === array[j]) {
array.splice(j, 1);
j--;
}
}
}
};
exports.removeDuplicates = removeDuplicates;
const chunk = (array, size) => {
const chunked = [];
for (let i = 0; i < array.length; i += size) {
chunked.push(array.slice(i, i + size));
}
return chunked;
};
exports.chunk = chunk;
const randomSample = (array, size) => {
const sample = [];
for (let i = 0; i < size; i++) {
const index = Math.floor(Math.random() * array.length);
sample.push(array[index]);
}
return sample;
};
exports.randomSample = randomSample;
const mean = (array) => {
return array.reduce((sum, current) => sum + current, 0) / array.length;
};
exports.mean = mean;
const median = (array) => {
array.sort((a, b) => a - b);
const middle = Math.floor(array.length / 2);
if (array.length % 2 === 0) {
return (array[middle - 1] + array[middle]) / 2;
}
else {
return array[middle];
}
};
exports.median = median;
const mode = (array) => {
const frequency = {};
let maxFrequency = 0;
let mode = array[0];
for (const element of array) {
frequency[element] = (frequency[element] || 0) + 1;
if (frequency[element] > maxFrequency) {
maxFrequency = frequency[element];
mode = element;
}
}
return mode;
};
exports.mode = mode;
function variance(array) {
// check if array is empty
if (array.length === 0) {
return 0;
}
// check if array has nested objects
if ((0, helpers_1.isArrayOfObjects)(array)) {
const key = arguments[1];
const values = array.map((obj) => obj[key]);
return variance(values);
}
// check if array has strings
if ((0, helpers_1.isArrayOfStrings)(array)) {
return NaN;
}
// check if array has numbers
if ((0, helpers_1.isArrayOfNumbers)(array)) {
const mean = array.reduce((a, b) => a + b) / array.length;
const squaredDifferences = array.map((num) => Math.pow(num - mean, 2));
return squaredDifferences.reduce((a, b) => a + b) / array.length;
}
// check if array has nested arrays
if ((0, helpers_1.isArrayOfArrays)(array)) {
const flattened = array.flat();
return variance(flattened);
}
// calculate the mean
const mean = array.reduce((a, b) => a + b) / array.length;
// calculate the squared differences
const squaredDifferences = array.map((num) => Math.pow(num - mean, 2));
// calculate the variance
return squaredDifferences.reduce((a, b) => a + b) / array.length;
}
exports.variance = variance;
const standardDeviation = (array) => {
return Math.sqrt(variance(array));
};
exports.standardDeviation = standardDeviation;
const countOccurrences = (array, element) => {
return array.reduce((count, current) => (current === element ? count + 1 : count), 0);
};
exports.countOccurrences = countOccurrences;
const zip = (...arrays) => {
const maxLength = Math.max(...arrays.map((array) => array.length));
return Array.from({ length: maxLength }).map((_, index) => arrays.map((array) => array[index]));
};
exports.zip = zip;
const unzip = (array) => {
return array[0].map((_, index) => array.map((array) => array[index]));
};
exports.unzip = unzip;
const rotate = (array, positions) => {
const rotated = array.slice();
for (let i = 0; i < positions; i++) {
rotated.unshift(rotated.pop());
}
return rotated;
};
exports.rotate = rotate;
const flip = (array) => {
return array.reverse();
};
exports.flip = flip;
const mirror = (array) => {
return array.concat(array.slice().reverse());
};
exports.mirror = mirror;
const isSorted = (data, compareFn, direction, findByKey) => {
const values = Array.isArray(data)
? data
: findByKey
? Object.values(data).map((val) => val[findByKey])
: Object.values(data);
let compare = compareFn;
if (direction) {
compare = direction === 'asc' ? compareFn : (a, b) => -compareFn(a, b);
}
// add a check for undefined values before comparing
for (let i = 0; i < values.length - 1; i++) {
if (values[i] === undefined || values[i + 1] === undefined) {
return false;
}
if (compare(values[i], values[i + 1]) > 0) {
return false;
}
}
return true;
};
exports.isSorted = isSorted;
const isEqual = (array1, array2) => {
return (array1.length === array2.length &&
array1.every((element, index) => element === array2[index]));
};
exports.isEqual = isEqual;
const swap = (array, index1, index2) => {
;
[array[index1], array[index2]] = [array[index2], array[index1]];
};
exports.swap = swap;
const move = (array, from, to) => {
array.splice(to, 0, array.splice(from, 1)[0]);
};
exports.move = move;
const fill = (array, value) => {
for (let i = 0; i < array.length; i++) {
array[i] = value;
}
};
exports.fill = fill;
const reverseFill = (array, value) => {
for (let i = array.length - 1; i >= 0; i--) {
array[i] = value;
}
};
exports.reverseFill = reverseFill;
const findFirst = (array, callback) => {
for (const element of array) {
if (callback(element)) {
return element;
}
}
return undefined;
};
exports.findFirst = findFirst;
const findLast = (array, callback) => {
return findFirst(array.slice().reverse(), callback);
};
exports.findLast = findLast;
const remove = (data, index, count) => {
if (Array.isArray(data)) {
if (typeof index === 'function') {
index = data.findIndex(index);
count = 1;
}
return (0, helpers_1.removeArray)(data, index, count);
}
return data;
};
exports.remove = remove;
const insert = (array, index, ...elements) => {
array.splice(index, 0, ...elements);
};
exports.insert = insert;
const merge = (array1, array2) => {
return array1.concat(array2);
};
exports.merge = merge;
const pad = (array, padding, repeat) => {
return [
...Array(repeat).fill(padding),
...array,
...Array(repeat).fill(padding),
];
};
exports.pad = pad;
const repeat = (array, repeat) => {
let repeatedArray = Array.from({ length: repeat }, () => array);
return repeatedArray.flat();
};
exports.repeat = repeat;
const range = (array) => {
array.sort((a, b) => a - b);
return [array[0], array[array.length - 1]];
};
exports.range = range;
const countBy = (array, callback) => {
return array.reduce((counts, element) => {
const key = callback(element);
counts[key] = (counts[key] || 0) + 1;
return counts;
}, {});
};
exports.countBy = countBy;
const deepSearch = (input, pattern, startIndex = 0) => {
let idx = startIndex;
while (true) {
const slice = input.slice(idx, idx + pattern.length);
if (slice.length === 0) {
return undefined;
}
let found = true;
for (let i = 0; i < pattern.length; i++) {
if (Array.isArray(pattern[i]) || typeof pattern[i] === 'object') {
found = deepSearch(input, pattern[i], idx + i);
}
else if (slice[i] !== pattern[i]) {
found = false;
}
if (!found) {
break;
}
}
if (found) {
return idx;
}
idx += 1;
}
};
exports.deepSearch = deepSearch;