rotate
Returns a new array with elements rotated left or right by n
positions. Positive n
rotates to the left, negative n
to the right. The original array remains unchanged.
1/**
2 * Returns a new array with elements rotated left or right by 'n' positions.
3 * Positive 'n' rotates to the left, negative 'n' to the right.
4 * The original array remains unchanged.
5 *
6 * @param arr - The array to rotate.
7 * @param n - Number of positions to rotate (positive or negative).
8 * @returns A new rotated array.
9 */
10export function rotate<T>(arr: T[], n: number): T[] {
11 const len = arr.length;
12 if (len === 0) return [];
13
14 const offset = ((n % len) + len) % len;
15 return [...arr.slice(offset), ...arr.slice(0, offset)];
16}
Supports both directions
Handles left and right rotations with the same logic using positive and negative values of
n
.Modulo-safe offset calculation
Normalizes rotation count to prevent redundant cycles (e.g., rotating by
n
whenn > array.length
), ensuring consistent behavior.Edge case resilient
Returns an empty array if the input is empty and avoids errors for excessive or negative values of
n
.Type-safe generic
Preserves the element type in the output, making it suitable for arrays of any type.
Immutable
Returns a new array without altering the original, maintaining functional programming safety.
Tests | Examples
1test('rotate - left rotation', () => {
2 expect(rotate([1, 2, 3, 4], 1)).toEqual([2, 3, 4, 1]);
3});
4
5test('rotate - right rotation', () => {
6 expect(rotate([1, 2, 3, 4], -1)).toEqual([4, 1, 2, 3]);
7});
8
9test('rotate - full rotation returns original', () => {
10 expect(rotate([1, 2, 3], 3)).toEqual([1, 2, 3]);
11 expect(rotate([1, 2, 3], -3)).toEqual([1, 2, 3]);
12});
13
14test('rotate - over-length rotations', () => {
15 expect(rotate([1, 2, 3], 4)).toEqual([2, 3, 1]);
16 expect(rotate([1, 2, 3], -4)).toEqual([3, 1, 2]);
17});
18
19test('rotate - empty array', () => {
20 expect(rotate([], 2)).toEqual([]);
21});
22
23test('rotate - single element', () => {
24 expect(rotate([42], 5)).toEqual([42]);
25});
Common Use Cases
Cyclic data manipulation
Useful when working with ring buffers, round-robin scheduling, or carousel-type features.
UI logic
Helps in rotating banners, featured items, or slides without altering original data sources.
Time series and calendar data
Rotates data like weekdays or monthly sequences for dynamic presentations or calculations.
Game mechanics
Rotating player turns or board states in turn-based games.
Data preprocessing
Reorders datasets cyclically before applying further transformation or aggregation.