-2

let arr = [1, 2, 3, 4, 5]
let steps = 2
let hold = arr
let indlength = arr.length - 1
for (let i = indlength; i > indlength - steps; i--) {
  hold.unshift(arr[i])
  hold.pop()
}

console.log(hold)

So I am attempting to rotate this array in javascript to the right by 2 rotations. Instead of getting 4,5,1,2,3 I am getting 3,5,1,2,3. I suspect it has something to do with an index being skipped, because if I up the steps to 3, it becomes 1,3,5,1,2. Here is a repl link https://repl.it/@helixlamont/ExoticTealOpengl

Bhargav Rao
  • 41,091
  • 27
  • 112
  • 129
Helix
  • 1

4 Answers4

1

The problem is the reference you're keeping when you do this let hold = arr; You should create a real copy/clone of arr.

An alternative is using the spread-syntax.

let arr = [1, 2, 3, 4, 5],
    steps = 2,
    hold = [...arr],
    indlength = arr.length - 1;

for (let i = indlength; i > indlength - steps; i--) {
  hold.unshift(arr[i]);
  hold.pop();
}

console.log(hold)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ele
  • 31,191
  • 6
  • 31
  • 67
  • thank you @Ele , so what is the difference between the reference I created and your copy? Why is [...arr] considered a real copy? – Helix Feb 22 '19 at 18:18
  • @Helix your approach is keeping the same reference in `arr` and `hold`, so the modifications in `hold` are hitting the array `arr`. Now, the spread-operator is doing the following `[...arr] === [1, 2, 3, 4, 5]`, so this a real copy/clone. – Ele Feb 22 '19 at 18:20
  • that works is very tricky and not obvious, because you use two different arrays for changing an array and keeping the other. – Nina Scholz Feb 22 '19 at 18:21
  • @NinaScholz probably the exercise is to avoid any mutation on the original array. – Ele Feb 22 '19 at 18:22
  • @Ele I tried it without a reference/clone first, but the same thing happened. I thought the problem was happening because I was mutating the original array. Turns out I was mutating it anyway by not creating a real clone like Ele mentioned. Still can't figure out why the indexes are skipping like that though if you don't use a clone. – Helix Feb 22 '19 at 18:32
  • @ NinaScholz I tried it without a reference/clone first, but the same thing happened. I thought the problem was happening because I was mutating the original array. Turns out I was mutating it anyway by not creating a real clone like Ele mentioned. Still can't figure out why the indexes are skipping like that though if you don't use a clone. – Helix Feb 22 '19 at 18:33
0

You code does not work as desired, because you change the index for unshifting the value. It is starting from the last index and going to zero. The result is some missing values.

By taking always the last index, you get the wanted result.


I would not use one array as source and manipulate another array, with the same object reference. For keeping a consistent approach, I would use only one of it.

let arr = [1, 2, 3, 4, 5]
let steps = 2
let hold = arr
let indlength = arr.length - 1
for (let i = indlength; i > indlength - steps; i--) {
  console.log(hold.join(' '));
  hold.unshift(hold[indlength]); // take the last value and use hold instead of arr
  hold.pop();
}

console.log(hold.join(' '));

A siplified version, is to pop (the last value) and unshift it (at the front of the array). The length of the array is constant.

let array = [1, 2, 3, 4, 5],
    steps = 2,
    i;

for (i = 0; i < steps; i++) {
    console.log(array.join(' '));
    array.unshift(array.pop());        
}

console.log(array.join(' '));
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324
  • 1
    You should explain what was wrong with his code, not just post your own code. Valid ways to rotate an array can be found in the question https://stackoverflow.com/questions/1985260/javascript-array-rotate – Barmar Feb 22 '19 at 18:03
  • @Barmar, please see edit. – Nina Scholz Feb 22 '19 at 18:15
  • Thank you @Nina Scholz I made it super complicated for myself for no reason – Helix Feb 22 '19 at 18:39
0

In your code problem is you're using reference of arr in let hold = arr.

Ele's answer has already added a working snippet of your code.

Other way of doing is using splice and concat

let arr = [1,2,3,4,5]
let steps = 2
let part1 = arr.splice(-steps)

console.log(part1.concat(arr))
Code Maniac
  • 33,907
  • 4
  • 28
  • 50
0

Others have described why your code isn't working. One simple non-mutating alternative is

const rotate = (steps, arr) => arr.slice(-steps).concat(arr.slice(0, -steps))

console.log(rotate(2, [1, 2, 3, 4, 5]))
console.log(rotate(-1, [1, 2, 3, 4, 5]))

If you wanted to rotate in the other direction, you could drop the negation signs.

This would fail if steps is larger than the length of the array. If you want it to keep rotating then, it's not much more difficult:

const rotate = (steps, arr) => 
  arr.slice(-(steps % arr.length)).concat(arr.slice(0, -(steps % arr.length)))
Scott Sauyet
  • 37,179
  • 4
  • 36
  • 82