'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;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow