How to Reverse Arrays in JavaScript Without Using .reverse()

How to Reverse Arrays in JavaScript Without Using .reverse()

In-Place & Out-of-Place

Image for postPhoto by Guillaume Bolduc on Unsplash

A typical JavaScript challenge or interview question has to do with reversing arrays in-place and out-of-place. Specifically, take this problem from Eloquent JavaScript, 2nd Edition:

Write two functions reverseArray and reverseArrayInPlace. The first, reverseArray, takes an array as an argument and produces a new array that has the same elements in the inverse order. The second, reverseArrayInPlace, does what the reverse method does: it modifies the array given as argument in order to reverse its elements. Neither may use the standard reverse method.

That?s the kicker: you can?t use the .reverse() method.

I worked through this problem in the past, but now that I am getting back to studying JavaScript after a break, it took me awhile to re-wrap my head around it. Especially reversing the array in-place. To help me better understand and think through this problem I decided to write this article.

Reversing an Array Out-of-Place

To start, let?s make up two arrays:

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

For the reverseArray function, if we?re going to produce a new array we need an empty array to fill up later:

var newArray = ;

Writing the steps out in pseudo-code:

// 1) I want to take the last element of the array, then add it to the newArray. // 2) To do this I’ll need to loop through the array from the end to the beginning, because I want the last element to be first.// 3) I want to output the contents of ‘newArray’ when the for loop is finished.

Let?s come up with our for loop first. To start at the end of the array we want to set i equal to the length of the array minus 1, since the index of an array always starts at zero.

var i = array.length – 1

For example, array1.length would give us 7 because there are seven elements in it. The index of each, however, is 0, 1, 2, 3, 4, 5, and 6. So in order to begin at the element with an index of 6 we?d need to take the length of the array and subtract 1.

Writing out our full for loop we get:

for (var i = arr.length – 1; i >= 0; i–)

In other words, we are subtracting 1 from the index with each loop until i is greater than or equal to 0, the beginning of the array. (Using arr as the parameter name in the below function is the same as using array. Don?t let that throw you!)

function reverseArray(arr) { var newArray = ; for (var i = arr.length – 1; i >= 0; i–) { newArray.push(arr[i]); } return newArray;}

arr[i] represents each element at its respective index. On the first loop through, arr[i] is the element “if”. On each loop we use the .push() method to literally ?push? arr[i] to the end of the newArray.

Passing array1 into this function we?d get:

reverseArray(array1)? [“if”, “never”, “sometimes”, “always”, “maybe”, “no”, “yes”]

Reversing an Array In-Place

Things immediately get more complicated for me when trying to reverse an array in-place. When I initially tried working through this problem I was trying to grab the first element using .shift(), setting that to a variable named first, then using .push() to add it to the end of the original array. But the problem I ran into is that I was just reversing the first and last elements over and over again with each loop, because .shift() only removes elements at the ?zeroeth index? and .pop() at the last.

There was also the problem of where to start and end the for loop.

Before going further, though, let?s write out the problem in pseudo-code:

// 1) I know I need to loop through the array. But before figuring out where to start or end I need to think about how I will actually reverse the elements in the array.// 2) The only way I can think to do this is to switch the first element with the last element, then the second element with the second-to-last element, etc., until I reach the middle.

So in terms of our for loop, I can start at the beginning or the end of the array, and finish when i is half the length of the array.

The way I initially thought to do this was:

for (var i = 0; i <= (arr.length / 2); i++)

I then set the first element equal to a variable called el, then set the first element equal to the last, and the last equal to the first (el).

Here?s how it looks:

let el = arr[i];arr[i] = arr[arr.length – 1 – i];arr[arr.length – 1 – i] = el;

So with each loop, el would be reset to equal the next element in the array.

arr[arr.length ? 1 ? i] is just a way of saying:

  1. On the first loop, the index is the length of the array, minus 1, minus the value of i, which is 0. Using array1 as an example, it would be: 8 ? 1 ? 0 = 7. arr[7]is the last element of array1, which is “if”.
  2. On the second loop, it would be: 8 ? 1 ? 1 = 6. Therefore, arr[6] would be the second-to-last element of array1, which is “never”. On and on until reaching the middle of the array.

Attempting it this way, it looks like:

function reverseArrayInPlace(arr) { for (var i = 0; i <= (arr.length / 2); i++) { let el = arr[i]; arr[i] = arr[arr.length – 1 – i]; arr[arr.length – 1 – i] = el; } return arr;}

But in testing this, something odd happens with arrays that have an even length, such as array2:

reverseArrayInPlace(array2)? [1, 3, 6, 9, 5, 2, 8, 5]

9 and 5 are reversed in the middle!

In cases where our array is an odd number, like array1, using i <= (arr.length / 2) would work, because array1.length is 3.5, and the loop would continue as long is i is less than or equal to 3.5. But if our length is 8, as it is in array2, then the loop will stop at index 4, which is actually 1 index past where we want to stop. Because the index starts at 0, we actually want to stop at 3.

To fix this we can subtract 1 from the length of the array before dividing it by 2. For good measure we can throw Math.floor in front to round decimals down to the nearest whole number.

function reverseArrayInPlace(arr) { for (var i = 0; i <= Math.floor((arr.length – 1) / 2); i++) { let el = arr[i]; arr[i] = arr[arr.length – 1 – i]; arr[arr.length – 1 – i] = el; } return arr;}

To review:

  • We started at the beginning of the array in our for loop.
  • We moved through the array until we reached the halfway point.
  • With each loop we set the element at i ? or arr[i] ? equal to a variable called el.
  • Then we set the first element equal to the last, and the last element equal to the first.
  • With each subsequent loop, as we moved inward we did the same thing.

I?m a JavaScript rookie, so if you have a more efficient way of doing this I?d love to hear from you in the comments section below!

function letsConnect(yes) { if (yes === true) { console.log(“linkedIn”); console.log(“Twitter”); } else { console.log(“thanks for reading!”); }}

1

No Responses

Write a response