Skip to content

Commit

Permalink
add compact map
Browse files Browse the repository at this point in the history
  • Loading branch information
therialguz committed Nov 8, 2024
1 parent a2a32d4 commit e1121c5
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/compactMap/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { describe, it, expect } from "vitest";
import { compactMap } from "./index";

describe("compactMap", () => {
it("should map and filter out null and undefined values", async () => {
const array = [1, 2, 3, 4, 5];
const result = await compactMap(array, (value) =>
value % 2 === 0 ? value * 2 : null
);
expect(result).toEqual([4, 8]);
});

it("should handle an empty array", async () => {
const array: number[] = [];
const result = await compactMap(array, (value) => value * 2);
expect(result).toEqual([]);
});

it("should handle a promise that resolves to an array", async () => {
const arrayPromise = Promise.resolve([1, 2, 3, 4, 5]);
const result = await compactMap(arrayPromise, (value) =>
value % 2 === 0 ? value * 2 : null
);
expect(result).toEqual([4, 8]);
});

it("should handle a callback that returns undefined", async () => {
const array = [1, 2, 3, 4, 5];
const result = await compactMap(array, (value) =>
value % 2 === 0 ? undefined : value
);
expect(result).toEqual([1, 3, 5]);
});

it("should handle a callback that returns a mix of values", async () => {
const array = [1, 2, 3, 4, 5];
const result = await compactMap(array, (value) =>
value % 2 === 0 ? value * 2 : null
);
expect(result).toEqual([4, 8]);
});
});
40 changes: 40 additions & 0 deletions src/compactMap/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { cooperate } from "../cooperate";
import { forEach } from "../forEach";

/**
* Maps each element of an array to a new value and filters out null and undefined values.
*
* @template T - The type of the elements in the array.
* @template U - The type of the mapped values.
*
* @param arrayOrPromise - An array or a promise that resolves to an array.
* @param callbackfn - A function that maps each element of the array to a new value. If the function returns null or undefined, the value is filtered out.
* @returns A promise that resolves to an array of mapped values.
*
* @example
* const array = [1, 2, 3, 4, 5];
* const result = await compactMap(array, (value) =>
* value % 2 === 0 ? value * 2 : null
* );
* console.log(result); // [4, 8]
*/
export const compactMap = async <T, U>(
arrayOrPromise: T[] | Promise<T[]>,
callbackfn: (value: T, index: number, array: T[]) => U | null | undefined
): Promise<U[]> => {
const array =
arrayOrPromise instanceof Promise ? await arrayOrPromise : arrayOrPromise;

return cooperate(async () => {
const result: U[] = [];

await forEach(array, (value, index, array) => {
const mappedValue = callbackfn(value, index, array);
if (mappedValue != null) {
result.push(mappedValue);
}
});

return result;
});
};

0 comments on commit e1121c5

Please sign in to comment.