4

I have a Javascript function called reverseArray that takes an array as the argument and returns a new array which has the same values as the input array in reverse order. I want to create a function called reverseArryInPlace which would change the value of the input array to the reverse order.

function reverseArray(inputArray) {
  var outputArray = [];
  for (var i = inputArray.length - 1; i >= 0; i--)
    outputArray.push(inputArray[i]);
  return outputArray;
}

function reverseArrayInPlace(inPlaceInputArray) {
  inPlaceInputArray = reverseArray(inPlaceInputArray);
  console.log('Inside reverseArrayInPlace: ' + inPlaceInputArray);
  return inPlaceInputArray;
}

var arrayValue = [1, 2, 3, 4, 5];
reverseArrayInPlace(arrayValue);
console.log('Outside reverseArrayInPlace: ' + arrayValue);
// Expected Value: [5, 4, 3, 2, 1]

Here is the result I get when I execute this chunk of code:

Inside reverseArrayInPlace: 5,4,3,2,1
Outside reverseArrayInPlace: 1,2,3,4,5

Within the reverseArrayInPlace function the arrayValue variable has been reversed as expected. Why is it that when I reference the same variable outside the reverseArrayInPlace function, it is back to the original order?

AGP
  • 41
  • 1
  • 4

4 Answers4

2

If you want to reverse it in place, you have to reverse it in place.

function reverseArrayInPlace(array) {
  for (let i = 0, j = array.length - 1; i < j; i++, j--) 
    [array[i], array[j]] = [array[j], array[i]];
}

const a = [1,2,3,4,5];
reverseArrayInPlace(a);
console.log(a);
  • okay, can you explain what's goin on in [x,y]=[y,x] statement? –  Apr 19 '17 at 05:04
  • `[a, b] = [b, a]` swaps the values of `a` and `b`, using [array destructuring assignment](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Swapping_variables).. –  Apr 19 '17 at 05:06
  • 1
    Why is it that the global variable (a) changes when you reassign the individual indexes of the array but when I reassign the entire array the global variable does not change? – AGP Apr 19 '17 at 05:25
1

The underlying problem here is that primitives are passed by value in JavaScript. See the following question for details:

Javascript by reference vs. by value

As a simple example, here is a function that attempts to mutate a string that was passed to it:

var outsideValue = 'foo'

function mutate(value) {
  value = 'fish'
}

mutate(outsideValue);
console.log(outsideValue);

However, the console output is foo.

This happens because the value variable within the mutate function is a variable that has a reference to outsideValue when the function is initially invoked. When it is assigned the new value within the function body, it merely changes the value variable to reference a new string. As a result, the outsideValue is untouched.

Check this answer for an example that reverses in place:

https://stackoverflow.com/a/43486686/249933

Notice, that it does not re-assign the function argument.

Community
  • 1
  • 1
ColinE
  • 68,894
  • 15
  • 164
  • 232
  • 1
    Primitives are passed by value, *value* doesn't have a reference to the value of *outsideValue*, it has a copy of the value. If the value was a reference (to an object), then yes, they would both reference the same object. But in that case, the value is a reference, not a primitive. ;-) – RobG Apr 19 '17 at 04:56
  • So now I understand that by resigning the array argument I am not actually changing the global variable. But in the example answer we are instead reassigning the individual indices of the array argument. How come the global variable is changed when we do this? – AGP Apr 19 '17 at 05:20
  • @AGP, that's the difference between a object reference and a primitive value. Primitives can't be changed, only the variables holding them can be overwritten (with new values). Every time I assign them to a new variable they are passed as a copy. Objects are passed as a reference. Behind the scenes, the address in memory where to find this object. If I change some property of an Object, the Object itself is changed, and therefore everyone that knows that object "has" this change. – Thomas Apr 19 '17 at 05:38
0

As others have said, arrays are objects so they're passed by reference. You have to modify the original array, not create a new one.

So here's another version of reverseInPlace, it uses shift to remove the last element from the array and splice to insert it in the new location:

function reverseInPlace(arr) {
  var i = arr.length;
  while (i--) {
    arr.splice(i, 0, arr.shift());
  }
}

var arr = [1,2,3,4,5];
console.log('Before: ' + arr.join());

reverseInPlace(arr);
console.log('After:  ' + arr.join());

For some fun, you can also leverage sort:

NB: this only works in some browsers, it's dependent on the built-in sort algorithm which is implementation dependent.

function reverseInPlace(arr) {
  arr.sort(() => 1);
}

var arr = [47, 95, 80, 62, 8, 34, 31, 17, 62, 17, 85, 72, 51, 20, 68, 60, 30, 84, 7, 34];
console.log('Before: ' + arr.join());

reverseInPlace(arr);
console.log('After : ' + arr.join());
RobG
  • 142,382
  • 31
  • 172
  • 209
  • Unfortunately, your "fun" version does not work. It's dependent on the internal sort algorithm and the order in which the sort function is being called. To see this, try something like `Array.from({length: 100}, _ => Math.floor(Math.random() * 100)).sort(() => 1)`. –  Apr 19 '17 at 05:29
  • @torazaburo—it "works" for me in Firefox 38, (but fails in IE). ;-) I wondered about that, nice to have confirmation that my suspicions were well founded. – RobG Apr 19 '17 at 05:51
  • I think it has to do with the browser switching to a different algorithm depending on the size of the array. –  Apr 19 '17 at 06:07
-2
function reverseArray(inputArray) {
  var outputArray = [];
  for (var i = inputArray.length - 1; i >= 0; i--)
    outputArray.push(inputArray[i]);
  return outputArray;
}

function reverseArrayInPlace(inPlaceInputArray) {
  inPlaceInputArray = reverseArray(inPlaceInputArray);
  console.log('Inside reverseArrayInPlace: ' + inPlaceInputArray);
  return inPlaceInputArray;
}
var arrayValue = [1, 2, 3, 4, 5];
**arrayValue = reverseArrayInPlace(arrayValue);**
alert('Outside reverseArrayInPlace: ' + arrayValue);
// Expected Value: [5, 4, 3, 2, 1]

//

your code is correct your just need to replace one line and write arrayValue = reverseArrayInPlace(arrayValue); instead of reverseArrayInPlace(arrayValue); Then arratValue will print expected values

NEO
  • 1
  • 3
  • This will not reverse it in place. It will replace the value of `arrayValue` iwth a **new** array. –  Apr 19 '17 at 05:09
  • Then we need to add new variable and print that instead of arrayValue like : var reversedValue = reverseArrayInPlace(arrayValue); then print this new value alert('Outside reverseArrayInPlace: ' + reversedValue); – NEO Apr 19 '17 at 05:11
  • You're not fully comprehending the meaning of **in place**. –  Apr 19 '17 at 05:13
  • This is totally clear. AGP wants to print reversed array in arrayValue variable your can see it in his code and the question he has asked. using this line "arrayValue = reverseArrayInPlace(arrayValue);" will definitely resolve his issue. Please read the question again then you will understand it clearly. – NEO Apr 19 '17 at 05:17
  • @NEO—this isn't what the OP wants. You're creating a new array (`var outputArray = []`), then assigning a reference to it to the original variable. The original array object still exists, unchanged, but is probably now ready for garbage collection. – RobG Apr 19 '17 at 06:15
  • Then use this function reverseArray(inputArray) { var outputArray = []; for (var i = inputArray.length - 1; i >= 0; i--) outputArray.push(inputArray[i]); return outputArray; } function reverseArrayInPlace() { arrayValue = reverseArray(arrayValue); console.log('Inside reverseArrayInPlace: ' + arrayValue); } var arrayValue = [1, 2, 3, 4, 5]; reverseArrayInPlace(arrayValue); alert('Outside reverseArrayInPlace: ' + arrayValue); // Expected Value: [5, 4, 3, 2, 1] – NEO Apr 19 '17 at 06:49
  • No need of inPlaceInputArray array variable just use arrayValue in reverseArrayInPlace function. still you need to assign reverseArray function value to array Value like. arrayValue = reverseArray(arrayValue); – NEO Apr 19 '17 at 06:50
  • No offense, but if you don't understand the terms in the question it's better to not write an answer. The OP wants to reverse the array **in place**. They already know how to do it by creating a new array. It isn't helpful in any way to show more ways to do the same thing. – JJJ Apr 19 '17 at 09:28