Add jsdoc and unit tests for util functions
This commit is contained in:
@@ -0,0 +1,130 @@
|
|||||||
|
import { describe, expect, it } from 'bun:test';
|
||||||
|
import { multArray, multBy, sumArray, sumBy } from './array.ts';
|
||||||
|
|
||||||
|
describe('array utils', () => {
|
||||||
|
it('sumArray number array', () => {
|
||||||
|
const array = [1, 2, 3];
|
||||||
|
const sum = sumArray(array);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(1 + 2 + 3);
|
||||||
|
|
||||||
|
expect(sumArray([])).toBeNumber();
|
||||||
|
expect(sumArray([])).toBeFinite();
|
||||||
|
expect(sumArray([])).toBe(0);
|
||||||
|
});
|
||||||
|
it('sumArray read-only number array', () => {
|
||||||
|
const array = [1, 2, 3] as const;
|
||||||
|
const sum = sumArray(array);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(1 + 2 + 3);
|
||||||
|
|
||||||
|
expect(sumArray([])).toBeNumber();
|
||||||
|
expect(sumArray([])).toBeFinite();
|
||||||
|
expect(sumArray([])).toBe(0);
|
||||||
|
});
|
||||||
|
it('sumBy number array', () => {
|
||||||
|
const array = [1, 2, 3];
|
||||||
|
const sum = sumBy(array, (e) => e);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(1 + 2 + 3);
|
||||||
|
});
|
||||||
|
it('sumBy read-only number array', () => {
|
||||||
|
const array = [1, 2, 3] as const;
|
||||||
|
const sum = sumBy(array, (e) => e);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(1 + 2 + 3);
|
||||||
|
});
|
||||||
|
it('sumBy mixed array', () => {
|
||||||
|
const array = [1, '2', 3.1, ''];
|
||||||
|
|
||||||
|
const sum = sumBy(array, (e) => e);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(1 + 2 + 3.1);
|
||||||
|
});
|
||||||
|
it('sumBy object array', () => {
|
||||||
|
const array: (
|
||||||
|
| { value: number | string }
|
||||||
|
| { differentValue: number | string }
|
||||||
|
)[] = [{ value: 3 }, { value: '2' }, { differentValue: '-2.44' }];
|
||||||
|
|
||||||
|
const sum = sumBy(array, (e) =>
|
||||||
|
'differentValue' in e ? e.differentValue : e.value
|
||||||
|
);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(3 + 2 - 2.44);
|
||||||
|
});
|
||||||
|
it('sumBy empty array', () => {
|
||||||
|
expect(sumBy([], (e) => e)).toBeNumber();
|
||||||
|
expect(sumBy([], (e) => e)).toBeFinite();
|
||||||
|
expect(sumBy([], (e) => e)).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('multArray number array', () => {
|
||||||
|
const array = [1, 2, 3];
|
||||||
|
const sum = multArray(array);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(2 * 3);
|
||||||
|
|
||||||
|
expect(multArray([])).toBeNumber();
|
||||||
|
expect(multArray([])).toBeFinite();
|
||||||
|
expect(multArray([])).toBe(0);
|
||||||
|
});
|
||||||
|
it('multArray read-only number array', () => {
|
||||||
|
const array = [1, 2, 3] as const;
|
||||||
|
const sum = multArray(array);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(2 * 3);
|
||||||
|
|
||||||
|
expect(multArray([])).toBeNumber();
|
||||||
|
expect(multArray([])).toBeFinite();
|
||||||
|
expect(multArray([])).toBe(0);
|
||||||
|
});
|
||||||
|
it('multBy number array', () => {
|
||||||
|
const array = [1, 2, 3];
|
||||||
|
const sum = sumBy(array, (e) => e);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(1 + 2 + 3);
|
||||||
|
});
|
||||||
|
it('multBy read-only number array', () => {
|
||||||
|
const array = [1, 2, 3] as const;
|
||||||
|
const sum = multBy(array, (e) => e);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(1 + 2 + 3);
|
||||||
|
});
|
||||||
|
it('multBy mixed array', () => {
|
||||||
|
const array = [1, '2', 3.1, ''];
|
||||||
|
|
||||||
|
const sum = multBy(array, (e) => e);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(0);
|
||||||
|
});
|
||||||
|
it('multBy object array', () => {
|
||||||
|
const array: (
|
||||||
|
| { value: number | string }
|
||||||
|
| { differentValue: number | string }
|
||||||
|
)[] = [{ value: 3 }, { value: '2' }, { differentValue: '-2.44' }];
|
||||||
|
|
||||||
|
const sum = multBy(array, (e) =>
|
||||||
|
'differentValue' in e ? e.differentValue : e.value
|
||||||
|
);
|
||||||
|
expect(sum).toBeNumber();
|
||||||
|
expect(sum).toBeFinite();
|
||||||
|
expect(sum).toBe(3 * 2 * -2.44);
|
||||||
|
});
|
||||||
|
it('multBy empty array', () => {
|
||||||
|
expect(multBy([], (e) => e)).toBeNumber();
|
||||||
|
expect(multBy([], (e) => e)).toBeFinite();
|
||||||
|
expect(multBy([], (e) => e)).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
+40
-11
@@ -1,21 +1,41 @@
|
|||||||
export function sumArray(arr: Array<number>): number {
|
/**
|
||||||
|
* Returns the sum of all the elements of a numeric array.
|
||||||
|
* @param arr Numeric array.
|
||||||
|
*/
|
||||||
|
export function sumArray(arr: ReadonlyArray<number>): number {
|
||||||
return sumBy(arr, (a) => a);
|
return sumBy(arr, (a) => a);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sumBy<T>(
|
/**
|
||||||
arr: Array<T>,
|
* Returns the sum of all the elements of any array,
|
||||||
by: (array: T) => number | string
|
* given a lamda function to receive the numeric representation of each element.
|
||||||
|
* @param arr Any array.
|
||||||
|
* @param by Map element to number or string, which will be interpreted as a number.
|
||||||
|
*/
|
||||||
|
export function sumBy<E>(
|
||||||
|
arr: ReadonlyArray<E>,
|
||||||
|
by: (element: E) => number | string
|
||||||
): number {
|
): number {
|
||||||
return arr.reduce((sum, element) => sum + Number(by(element)), 0);
|
return arr.reduce((sum, element) => sum + Number(by(element)), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function multArray(arr: Array<number>): number {
|
/**
|
||||||
|
* Returns the product of a numeric array.
|
||||||
|
* @param arr Numeric array.
|
||||||
|
*/
|
||||||
|
export function multArray(arr: ReadonlyArray<number>): number {
|
||||||
return multBy(arr, (a) => a);
|
return multBy(arr, (a) => a);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function multBy<T>(
|
/**
|
||||||
arr: Array<T>,
|
* Returns the product of any array,
|
||||||
by: (array: T) => number | string
|
* given a lamda function to receive the numeric representation of each element.
|
||||||
|
* @param arr Any array.
|
||||||
|
* @param by Map element to number or string, which will be interpreted as a number.
|
||||||
|
*/
|
||||||
|
export function multBy<E>(
|
||||||
|
arr: ReadonlyArray<E>,
|
||||||
|
by: (element: E) => number | string
|
||||||
): number {
|
): number {
|
||||||
if (arr.length <= 0) {
|
if (arr.length <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -23,19 +43,28 @@ export function multBy<T>(
|
|||||||
return arr.reduce((sum, element) => sum * Number(by(element)), 1);
|
return arr.reduce((sum, element) => sum * Number(by(element)), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group an array by a given key.
|
||||||
|
* @param arr Any array.
|
||||||
|
* @param by Map element to key.
|
||||||
|
* @param equals Check if two keys are identical. Defaults to strict equality.
|
||||||
|
*/
|
||||||
export function groupBy<E, K>(
|
export function groupBy<E, K>(
|
||||||
arr: Array<E>,
|
arr: ReadonlyArray<E>,
|
||||||
by: (element: E) => K
|
by: (element: E) => K,
|
||||||
|
equals: (a: K, b: K) => boolean = (a, b) => a === b
|
||||||
): { key: K; elements: Array<E> }[] {
|
): { key: K; elements: Array<E> }[] {
|
||||||
return arr.reduce(
|
return arr.reduce(
|
||||||
(groups, element) => {
|
(groups, element) => {
|
||||||
const key = by(element);
|
const key = by(element);
|
||||||
const index = groups.findIndex((e) => e.key === key);
|
const index = groups.findIndex((e) => equals(e.key, key));
|
||||||
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
|
// New key found, add to group array.
|
||||||
groups.push({ key, elements: [element] });
|
groups.push({ key, elements: [element] });
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
const existing = groups[index];
|
const existing = groups[index];
|
||||||
existing.elements.push(element);
|
existing.elements.push(element);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { describe, expect, it } from 'bun:test';
|
||||||
|
import { randomInt } from './random.ts';
|
||||||
|
|
||||||
|
describe('random utils', () => {
|
||||||
|
it('randomInt', () => {
|
||||||
|
const from = -2;
|
||||||
|
const to = 6;
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
const number = randomInt(from, to);
|
||||||
|
expect(number).toBeNumber();
|
||||||
|
expect(number).toBeFinite();
|
||||||
|
expect(number).toBeInteger();
|
||||||
|
expect(number).toBeGreaterThanOrEqual(from);
|
||||||
|
expect(number).toBeLessThan(to);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* Returns a random integer between from and to, including from, excluding to.
|
||||||
|
* @param fromInclusive Lower bound, inclusive.
|
||||||
|
* @param toExclusive Upper Bound, exclusive.
|
||||||
|
*/
|
||||||
export function randomInt(fromInclusive: number, toExclusive: number): number {
|
export function randomInt(fromInclusive: number, toExclusive: number): number {
|
||||||
return (
|
return (
|
||||||
Math.floor(Math.random() * (toExclusive - fromInclusive)) + fromInclusive
|
Math.floor(Math.random() * (toExclusive - fromInclusive)) + fromInclusive
|
||||||
|
|||||||
Reference in New Issue
Block a user