What is the most efficient way to reverse an array in Javascript?

JavascriptArraysPerformance

Javascript Problem Overview


I was asked recently what was the most efficient way to reverse an array in Javascript. At the moment, I suggested using a for loop and fiddling with the array but then realized there is a native Array.reverse() method.

For curiosity's sake, can anyone help me explore this by showing examples or pointing in the right direction so I can read into this? Any suggestions regarding how to measure performance would be awesome too.

Javascript Solutions


Solution 1 - Javascript

Based on this setup:

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

Array.reverse(); is the first or second slowest!

The benchmarks are here:

https://jsperf.com/js-array-reverse-vs-while-loop/9

Across browsers, swap loops are faster. There are two common types of swap algorithms (see Wikipedia), each with two variations.

The two types of swap algorithms are temporary swap and XOR swap.

The two variations handle index calculations differently. The first variation compares the current left index and the right index and then decrements the right index of the array. The second variation compares the current left index and the length divided by half and then recalculates the right index for each iteration.

You may or may not see huge differences between the two variations. For example, in Chrome 18, the first variations of the temporary swap and XOR swap are over 60% slower than the second variations, but in Opera 12, both variations of the temporary swap and XOR swap have similar performance.

Temporary swap:

First variation:

function temporarySwap(array)
{
    var left = null;
    var right = null;
    var length = array.length;
    for (left = 0, right = length - 1; left < right; left += 1, right -= 1)
    {
        var temporary = array[left];
        array[left] = array[right];
        array[right] = temporary;
    }
    return array;
}

Second variation:

function temporarySwapHalf(array)
{
    var left = null;
    var right = null;
    var length = array.length;
    for (left = 0; left < length / 2; left += 1)
    {
        right = length - 1 - left;
        var temporary = array[left];
        array[left] = array[right];
        array[right] = temporary;
    }
    return array;
}

XOR swap:

First variation:

function xorSwap(array)
{
    var i = null;
    var r = null;
    var length = array.length;
    for (i = 0, r = length - 1; i < r; i += 1, r -= 1)
    {
        var left = array[i];
        var right = array[r];
        left ^= right;
        right ^= left;
        left ^= right;
        array[i] = left;
        array[r] = right;
    }
    return array;
}

Second variation:

function xorSwapHalf(array)
{
    var i = null;
    var r = null;
    var length = array.length;
    for (i = 0; i < length / 2; i += 1)
    {
        r = length - 1 - i;
        var left = array[i];
        var right = array[r];
        left ^= right;
        right ^= left;
        left ^= right;
        array[i] = left;
        array[r] = right;
    }
    return array;
}

There is another swap method called destructuring assignment: http://wiki.ecmascript.org/doku.php?id=harmony:destructuring

Destructuring assignment:

First variation:

function destructuringSwap(array)
{
    var left = null;
    var right = null;
    var length = array.length;
    for (left = 0, right = length - 1; left < right; left += 1, right -= 1)
    {
        [array[left], array[right]] = [array[right], array[left]];
    }
    return array;
}

Second variation:

function destructuringSwapHalf(array)
{
    var left = null;
    var right = null;
    var length = array.length;
    for (left = 0; left < length / 2; left += 1)
    {
        right = length - 1 - left;
        [array[left], array[right]] = [array[right], array[left]];
    }
    return array;
}

Right now, an algorithm using destructuring assignment is the slowest of them all. It is even slower than Array.reverse();. However, the algorithms using destructuring assignments and Array.reverse(); methods are the shortest examples, and they look the cleanest. I hope their performance gets better in the future.


Another mention is that modern browsers are improving their performance of array push and splice operations.

In Firefox 10, this for loop algorithm using array push and splice rivals the temporary swap and XOR swap loop algorithms.

for (length -= 2; length > -1; length -= 1)
{
    array.push(array[length]);
    array.splice(length, 1);
}

However, you should probably stick with the swap loop algorithms until many of the other browsers match or exceed their array push and splice performance.

Solution 2 - Javascript

In simple way you can do this using map.

let list = [10, 20, 30, 60, 90]
let reversedList = list.map((e, i, a)=> a[(a.length -1) -i]) // [90, 60...]

Solution 3 - Javascript

Native methods are always faster.

So use Array.reverse where possible. Otherwise an implementation that runs in O(1) would be best ;)

Otherwise just use something like this

var reverse = function(arr) {
   var result = [],
       ii = arr.length;
   for (var i = ii - 1;i !== 0;i--) {
       result.push(arr[i]);
   }
   return result;
}

Benchmark!

Interesting the loop is faster if you use all three stages of the for construct instead of only one.

for(var i = ii - 1; i !== 0;i--) is faster then var i = ii - 1;for(;i-- !== 0;)

Solution 4 - Javascript

I opened a Firefox bug about slow reverse performance in Firefox. Someone from Mozilla looked at the benchmark used in the accepted post, and says that it is pretty misleading -- in their analysis the native method is better in general for reversing arrays. (As it should be!)

Solution 5 - Javascript

This is the most efficient and clean way to reverse an array with the ternary operator.

function reverse(arr) {
  return arr.length < 2 ? arr : [arr.pop()].concat(reverse(arr));
}
console.log(reverse([4, 3, 3, 1]));

Solution 6 - Javascript

Swap functions are the fastest. Here's a reverse function I wrote that is only slightly similar to the swap functions mentioned above but performs faster.

function reverse(array) {
  var first = null;
  var last = null;
  var tmp = null;
  var length = array.length;

  for (first = 0, last = length - 1; first < length / 2; first++, last--) {
    tmp = array[first];
    array[first] = array[last];
    array[last] = tmp;
  }
}

You can find the benchmarking here http://jsperf.com/js-array-reverse-vs-while-loop/19

Solution 7 - Javascript

Since no one came up with it and to complete the list of ways to reverse an array...

array.sort(function() {
    return 1;
})

It's twice as fast as both while-approaches, but other than that, horribly slow.

http://jsperf.com/js-array-reverse-vs-while-loop/53

Solution 8 - Javascript

You can do this with .slice().reverse():

const yourArray = ["first", "second", "third", "...", "etc"];
const reversedArray = yourArray.slice().reverse();
console.log(reversedArray);

Note that .slice() is used to prevent modification of yourArray since .reverse() is in-place.

Solution 9 - Javascript

Here's a java example http://www.leepoint.net/notes-java/data/arrays/arrays-ex-reverse.html showing how to reverse an array. Very easy to convert to javascript.

I would suggest using something that simply captures the time before the function is called, and after the function is called. Which ever takes the least time / clock cycles will be the fastest.

Solution 10 - Javascript

Here is another example to permanently modify the array reversing it's elements:

var theArray = ['a', 'b', 'c', 'd', 'e', 'f'];

function reverseArrayInPlace(array) {
  for (var i = array.length - 1; i >= 0; i -= 1) {
    array.push(array[i]);
  }
  array.splice(0, array.length / 2);
  return array;
};
reverseArrayInPlace(theArray);
console.log(theArray); // -> ["f", "e", "d", "c", "b", "a"]

Solution 11 - Javascript

Another suggestion, similar to the above, but using splice instead:

var myArray=["one","two","three","four","five","six"];
console.log(myArray);
for(i=0;i<myArray.length;i++){
myArray.splice(i,0,myArray.pop(myArray[myArray.length-1]));
}
console.log(myArray);

Solution 12 - Javascript

If you want to copy a reversed version of an array and keep the original as it is:

a = [0,1,2,3,4,5,6,7,8,9];
b = []
for(i=0;i<a.length;i++){
    b.push(a.slice(a.length-i-1,a.length-i)[0])
}

Output of b:

[ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Solution 13 - Javascript

Pasting the below into any javascript runtime console either on the browser or node.js would do a straight way benchmark test on a large array of number.

Say 40,000 in my case

var array = Array.from({ length: 40000 }, () =>
  Math.floor(Math.random() * 40000)
);
var beforeStart = Date.now();
var reversedArray = array.map((obj, index, passedArray) => {
  return passedArray[passedArray.length - index - 1];
});
console.log(reversedArray);
var afterCustom = Date.now();
console.log(array.reverse());
var afterNative = Date.now();
console.log(`custom took : ${afterCustom - beforeStart}ms`);
console.log(`native took : ${afterNative - afterCustom}ms`);

You can simply run the snippet directly to see how the custom version fare too.

Solution 14 - Javascript

For the sake of completeness there should be also thought about efficiency in a broader way, than only execution-time performance.

Therefore I'd like to add a swap function that is minimal slower (please test on your own using perf tools) than than the ones from the accepted answer but it has the following other beneficial properties:

  • it doesn't require a temp variable for swapping
  • it keeps the input array untouched
  • it works also with arrays of values other than numerical because it simply swaps references
  • it does not start a function call on every iteration step
  • it keeps being readable (although this could still be improved)

function fastSwapReverse (array) {
  // half length for odd arrays is added by 1
  var len = array.length;
  var half = len % 2 === 0 ? len / 2 : Math.ceil(len / 2)
  var k = 0, A = new Array(len)
      
  // from 0 to half swap the elements at
  // start: 0 + i
  // end: len - i -1
  for (k = 0; k < half; k++) {
    A[k] = array[len - k - 1];
    A[len - k - 1] = array[k];
  }
      
  return A;
}

Although the original Array.prototype.reverse method also does mutate the array

Solution 15 - Javascript

Just start copying array from the backside using a for loop and return that new array. This is efficient and has O(n) time complexity.

var array1 = ["yes", "no", "maybe", "always", "sometimes", "never", "if"];
var array2 = [5,8,2,9,5,6,3,1];

function reverseArray(arr) {
  var newArray = [];
  for (var x = arr.length - 1; 0 <= x; --x) {
    newArray.push(arr[x]);
  }
  return newArray;
}

console.log(reverseArray(array1)); // ["if", "never", "sometimes", "always", "maybe", "no", "yes"]
console.log(reverseArray(array2)) // [1, 3, 6, 5, 9, 2, 8, 5]

Solution 16 - Javascript

Here are a couple of tricks I found. Credit goes to Codemanx for the original solution of

> array.sort(function() { > return 1; > })

In Typescript, this can be simplified to just one line

array.sort(() => 1)

var numbers = [1,4,9,13,16];

console.log(numbers.sort(() => 1));

Since this will be the future of JavaScript, I thought I'd share that.

Here's another trick if your array only has 2 elements

array.push(array.shift());

Solution 17 - Javascript

You could also make use of reduceRight which will iterate through each value of the array (from right-to-left)

const myArray = [1, 2, 3, 4, 5]
const reversedArray = myArray.reduceRight((acc, curr) => [...acc, curr], [])
console.log(reversedArray) // [5, 4, 3, 2, 1]

Solution 18 - Javascript

// array-reverse-polyfill.js v1
Array.prototype.reverse = Array.prototype.reverse || function() {
	return this.sort(function() {
		return -1;
	});
};

If you are in a modern browser you use the native reverse function. If it's not modern this polyfill will add this function for you. So just use it:

I haven't found any cases where Firefox does the opposite behavior to other browsers. Anyway, if you want to ensure that the function will sort alphabetically, just do a little test first.

// array-reverse-polyfill.js v1.1
;(function(){
	var order = ['a', 'b'].sort(function(a, b){
		return -1;
	});
	order = order[0] === 'b' ? -1 : 1;
	Array.prototype.reverse = Array.prototype.reverse || function() {
		return this.sort(function() {
			return order;
		});
	};
})();

Example of use:

let a = [1,2,3,4,5];
a.reverse();
console.log(a);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionluisgoView Question on Stackoverflow
Solution 1 - JavascriptXP1View Answer on Stackoverflow
Solution 2 - JavascriptSrinivas DamamView Answer on Stackoverflow
Solution 3 - JavascriptRaynosView Answer on Stackoverflow
Solution 4 - JavascriptstarwedView Answer on Stackoverflow
Solution 5 - JavascriptArslan shakoorView Answer on Stackoverflow
Solution 6 - JavascriptBrice LinView Answer on Stackoverflow
Solution 7 - JavascriptCodeManXView Answer on Stackoverflow
Solution 8 - JavascriptKangudie Muanza - KillmongerView Answer on Stackoverflow
Solution 9 - JavascriptclamchodaView Answer on Stackoverflow
Solution 10 - JavascriptdrjorgepolancoView Answer on Stackoverflow
Solution 11 - JavascriptSlavCo ZuteView Answer on Stackoverflow
Solution 12 - JavascripttarikakyolView Answer on Stackoverflow
Solution 13 - JavascriptOlaawo OluwapelumiView Answer on Stackoverflow
Solution 14 - JavascriptJankapunktView Answer on Stackoverflow
Solution 15 - JavascriptEricgitView Answer on Stackoverflow
Solution 16 - JavascriptRichard HamiltonView Answer on Stackoverflow
Solution 17 - JavascriptNick DView Answer on Stackoverflow
Solution 18 - JavascriptLuis LoboView Answer on Stackoverflow