diff --git a/Data-Structures/Array/Unique.js b/Data-Structures/Array/Unique.js new file mode 100644 index 0000000000..d44a0d980c --- /dev/null +++ b/Data-Structures/Array/Unique.js @@ -0,0 +1,19 @@ +/** + * @function unique + * @description Returns a new array with all duplicate values removed, + * preserving the order of first occurrence. + * @param {Array} arr - The input array + * @returns {Array} - A new array with only unique values + * @see https://en.wikipedia.org/wiki/Set_(abstract_data_type) + * @example unique([1, 2, 2, 3]) => [1, 2, 3] + * @example unique([1, 1, 1]) => [1] + * @example unique([1, "1", 1]) => [1, "1"] + */ +const unique = (arr) => { + if (!Array.isArray(arr)) { + throw new TypeError('Input must be an array') + } + return [...new Set(arr)] +} + +export { unique } diff --git a/Data-Structures/Array/test/Unique.test.js b/Data-Structures/Array/test/Unique.test.js new file mode 100644 index 0000000000..e9aa226fbc --- /dev/null +++ b/Data-Structures/Array/test/Unique.test.js @@ -0,0 +1,45 @@ +import { unique } from '../Unique.js' + +describe('unique', () => { + test('unique([1, 2, 2, 3]) returns [1, 2, 3]', () => { + expect(unique([1, 2, 2, 3])).toEqual([1, 2, 3]) + }) + + test('unique([1, 1, 1]) returns [1]', () => { + expect(unique([1, 1, 1])).toEqual([1]) + }) + + test("unique([1, '1', 1]) returns [1, '1']", () => { + expect(unique([1, '1', 1])).toEqual([1, '1']) + }) + + test('unique([]) returns []', () => { + expect(unique([])).toEqual([]) + }) + + test('unique with no duplicates returns same values', () => { + expect(unique([1, 2, 3])).toEqual([1, 2, 3]) + }) + + test('unique preserves order of first occurrence', () => { + expect(unique([3, 1, 2, 1, 3])).toEqual([3, 1, 2]) + }) + + test('unique works with strings', () => { + expect(unique(['a', 'b', 'a', 'c'])).toEqual(['a', 'b', 'c']) + }) + + test('unique does not mutate original array', () => { + const arr = [1, 2, 2, 3] + unique(arr) + expect(arr).toEqual([1, 2, 2, 3]) + }) + + test('throws TypeError for non-array input', () => { + expect(() => unique('123')).toThrow(TypeError) + }) + + test('throws TypeError for null input', () => { + expect(() => unique(null)).toThrow(TypeError) + }) +})