'Reverse array in Javascript without mutating original array

Array.prototype.reverse reverses the contents of an array in place (with mutation)...

Is there a similarly simple strategy for reversing an array without altering the contents of the original array (without mutation)?



Solution 1:[1]

You can use slice() to make a copy then reverse() it

var newarray = array.slice().reverse();

var array = ['a', 'b', 'c', 'd', 'e'];
var newarray = array.slice().reverse();

console.log('a', array);
console.log('na', newarray);

Solution 2:[2]

In ES6:

const newArray = [...array].reverse()

Solution 3:[3]

Another ES6 variant:

We can also use .reduceRight() to create a reversed array without actually reversing it.

let A = ['a', 'b', 'c', 'd', 'e', 'f'];

let B = A.reduceRight((a, c) => (a.push(c), a), []);

console.log(B);

Useful Resources:

Solution 4:[4]

Try this recursive solution:

const reverse = ([head, ...tail]) => 
    tail.length === 0
        ? [head]                       // Base case -- cannot reverse a single element.
        : [...reverse(tail), head]     // Recursive case

reverse([1]);               // [1]
reverse([1,2,3]);           // [3,2,1]
reverse('hello').join('');  // 'olleh' -- Strings too!                              

Solution 5:[5]

There are multiple ways of reversing an array without modifying. Two of them are

var array = [1,2,3,4,5,6,7,8,9,10];

// Using Splice
var reverseArray1 = array.splice().reverse(); // Fastest

// Using spread operator
var reverseArray2 = [...array].reverse();

// Using for loop 
var reverseArray3 = []; 
for(var i = array.length-1; i>=0; i--) {
  reverseArray.push(array[i]);
}

Performance test http://jsben.ch/guftu

Solution 6:[6]

An ES6 alternative using .reduce() and spreading.

const foo = [1, 2, 3, 4];
const bar = foo.reduce((acc, b) => ([b, ...acc]), []);

Basically what it does is create a new array with the next element in foo, and spreading the accumulated array for each iteration after b.

[]
[1] => [1]
[2, ...[1]] => [2, 1]
[3, ...[2, 1]] => [3, 2, 1]
[4, ...[3, 2, 1]] => [4, 3, 2, 1]

Alternatively .reduceRight() as mentioned above here, but without the .push() mutation.

const baz = foo.reduceRight((acc, b) => ([...acc, b]), []);

Solution 7:[7]

const newArr = Array.from(originalArray).reverse();

Solution 8:[8]

const arrayCopy = Object.assign([], array).reverse()

This solution:

-Successfully copies the array

-Doesn't mutate the original array

-Looks like it's doing what it is doing

Solution 9:[9]

Reversing in place with variable swap just for demonstrative purposes (but you need a copy if you don't want to mutate)

const myArr = ["a", "b", "c", "d"];
const copy = [...myArr];
for (let i = 0; i < (copy.length - 1) / 2; i++) {  
    const lastIndex = copy.length - 1 - i; 
    [copy[i], copy[lastIndex]] = [copy[lastIndex], copy[i]] 
}

Solution 10:[10]

While array.slice().reverse() is what I would myself go for in a situation where I cannot use a library, it's not so good in terms of readability: we are using imperative logic that the person reading the code must think through. Considering also that there is the same problem with sort, there's a solid justification here for using a utility library.

You can use a function pipe from fp-ts or a library I've written myself. It pipes a value though a number of functions, so pipe(x, a, b) is equivalent to b(a(x)). With this function, you can write

pipe(yourArray, reverseArray)

where reverseArray is a function that basically does .slice().reverse(), i.e. reverses the array immutably. Generally speaking, pipe lets you do the equivalent of dot-chaining, but without being limited to the methods available on the array prototype.

Solution 11:[11]

There's a new tc39 proposal, which adds a toReversed method to Array that returns a copy of the array and doesn't modify the original.

Example from the proposal:

const sequence = [1, 2, 3];
sequence.toReversed(); // => [3, 2, 1]
sequence; // => [1, 2, 3]

As it's currently in stage 3, it will likely be implemented in browser engines soon, but in the meantime a polyfill is available here or in core-js.

Solution 12:[12]

Is there a similarly simple strategy for reversing an array without altering the contents of the original array (without mutation) ?

Yes, there is a way to achieve this by using to[Operation] that return a new collection with the operation applied (This is currently at stage 3, will be available soon).

Implementation will be like :

const arr = [5, 4, 3, 2, 1];

const sortedArr = arr.toReverse();

console.log(arr); // [5, 4, 3, 2, 1]

console.log(sortedArr); // [1, 2, 3, 4, 5]

Solution 13:[13]

INTO plain Javascript:

function reverseArray(arr, num) {
  var newArray = [];
  for (let i = num; i <= arr.length - 1; i++) {
    newArray.push(arr[i]);
  }

  return newArray;
}