diff --git a/benchmarks/range.bench.ts b/benchmarks/range.bench.ts new file mode 100644 index 000000000..28b859c17 --- /dev/null +++ b/benchmarks/range.bench.ts @@ -0,0 +1,13 @@ +import { bench, describe } from 'vitest'; +import { range as rangeToolkit } from 'es-toolkit'; +import { range as rangeLodash } from 'lodash'; + +describe('range', () => { + bench('es-toolkit/range', () => { + rangeToolkit(0, 100, 1); + }); + + bench('lodash/range', () => { + rangeLodash(0, 100, 1); + }); +}); diff --git a/src/array/index.ts b/src/array/index.ts index 0c1c1d428..09034bffb 100644 --- a/src/array/index.ts +++ b/src/array/index.ts @@ -11,6 +11,7 @@ export { intersection } from './intersection'; export { intersectionBy } from './intersectionBy'; export { intersectionWith } from './intersectionWith'; export { partition } from './partition'; +export { range } from './range'; export { sample } from './sample'; export { shuffle } from './shuffle'; export { take } from './take'; diff --git a/src/array/range.spec.ts b/src/array/range.spec.ts new file mode 100644 index 000000000..b705687c8 --- /dev/null +++ b/src/array/range.spec.ts @@ -0,0 +1,28 @@ +import { describe, expect, it } from 'vitest'; +import { range } from './range'; + +describe('range', () => { + it('handles positive range with default step', () => { + expect(range(4)).toEqual([0, 1, 2, 3]); + }); + + it('handles negative range with default step', () => { + expect(range(-4)).toEqual([0, -1, -2, -3]); + }); + + it('handles custom positive step', () => { + expect(range(0, 20, 5)).toEqual([0, 5, 10, 15]); + }); + + it('handles custom negative step', () => { + expect(range(0, -4, -1)).toEqual([0, -1, -2, -3]); + }); + + it('handles zero step', () => { + expect(range(1, 4, 0)).toEqual([1, 1, 1]); + }); + + it('handles zero range', () => { + expect(range(0)).toEqual([]); + }); +}); diff --git a/src/array/range.ts b/src/array/range.ts new file mode 100644 index 000000000..7fcc888a2 --- /dev/null +++ b/src/array/range.ts @@ -0,0 +1,48 @@ +/** + * Returns an array of numbers from `start` to `end` with the specified `step` value. + * + * This function generates a range of numbers, starting from `start`, ending before `end`, + * and incrementing by `step`. If `step` is not provided, it defaults to `1` for an + * ascending range and `-1` for a descending range. + * + * @param {number} start - The starting number of the range. + * @param {number} [end] - The end number of the range. + * @param {number} [step] - The step value for the range. + * @returns {number[]} An array of numbers from `start` to `end` with the specified `step`. + * + * @example + * // Returns [0, 1, 2, 3] + * range(4); + * + * @example + * // Returns [0, 5, 10, 15] + * range(0, 20, 5); + * + * @example + * // Returns [0, -1, -2, -3] + * range(0, -4, -1); + * + * @example + * // Returns [1, 1, 1] + * range(1, 4, 0); + */ + +export function range(start: number, end?: number, step?: number): number[] { + if (end === undefined) { + end = start; + start = 0; + } + + if (step === undefined) { + step = start <= end ? 1 : -1; + } + + const length = Math.max(Math.ceil((end - start) / (step || 1)), 0); + const result = new Array(length); + + for (let i = 0; i < length; i++) { + result[i] = start + i * step; + } + + return result; +}