diff --git a/src/array/reduce.spec.ts b/src/array/reduce.spec.ts new file mode 100644 index 000000000..4db01ddd9 --- /dev/null +++ b/src/array/reduce.spec.ts @@ -0,0 +1,39 @@ +import { describe, expect, it } from 'vitest'; +import { reduce } from './reduce'; + +describe('reduce', () => { + it('removes elements at specified indices and returns the removed elements', () => { + const arr = [10, 20, 30, 40, 50]; + const removed = reduce(arr, [1, 3, 4]); + expect(removed).toEqual([20, 40, 50]); + expect(arr).toEqual([10, 30]); + }); + + it('returns undefined for out-of-bounds indices', () => { + const arr = [10, 20, 30]; + const removed = reduce(arr, [10, -10]); + expect(removed).toEqual([undefined, undefined]); + expect(arr).toEqual([10, 20, 30]); + }); + + it('handles duplicate indices gracefully', () => { + const arr = [10, 20, 30, 40]; + const removed = reduce(arr, [1, 1, 3]); + expect(removed).toEqual([20, 40]); + expect(arr).toEqual([10, 30]); + }); + + it('removes all elements when all indices are specified', () => { + const arr = [10, 20, 30]; + const removed = reduce(arr, [0, 1, 2]); + expect(removed).toEqual([10, 20, 30]); + expect(arr).toEqual([]); + }); + + it('removes elements in descending order of indices', () => { + const arr = [10, 20, 30, 40, 50]; + const removed = reduce(arr, [4, 0, 2]); + expect(removed).toEqual([10, 30, 50]); + expect(arr).toEqual([20, 40]); + }); +}); diff --git a/src/array/reduce.ts b/src/array/reduce.ts new file mode 100644 index 000000000..071382adb --- /dev/null +++ b/src/array/reduce.ts @@ -0,0 +1,37 @@ +/* + * Removes elements from an array at specified indices and returns the removed elements. + * + * This function supports negative indices, which count from the end of the array. + * + * @template T + * @param {T[]} arr - The array from which elements will be removed. + * @param {number[]} indicesToRemove - An array of indices specifying the positions of elements to remove. + * @returns {Array} An array containing the elements that were removed from the original array. + * + * @example + * import { reduce } from './reduce'; + * + * const numbers = [10, 20, 30, 40, 50]; + * const removed = reduce(numbers, [1, 3, 4]); + * console.log(removed); // [20, 40, 50] + * console.log(numbers); // [10, 30] + */ +export function reduce(arr: T[], indicesToRemove: number[]): Array { + const indicesSet = Array.from( + new Set(indicesToRemove.map((index) => (index < 0 ? arr.length + index : index))) + ).sort((a, b) => b - a); + + const removed: Array = []; + + for (let i = 0; i < indicesSet.length; i++) { + const index = indicesSet[i]; + if (index >= 0 && index < arr.length) { + removed.unshift(arr[index]); // Add the removed element to the front + arr.splice(index, 1); // Remove the element from the array + } else { + removed.unshift(undefined); // Handle out-of-bounds indices + } + } + + return removed; + }