3

Okay, so I do not know if the title is right or not, but what I am struggling to do is find an algorithm to do something like this. So we have an input array such as: ['a','b', 'c', 'd', ...] until the end of the alphabet, and a number to shift with. I have to output the array like ['x', 'y', 'z', 'a', 'b', 'c', ...] if I have a number 3 to shift with; Any ideas on how to do it? I tried:

function solve(args)
{
    let arr = ['a', 'b', 'c', 'd'];
    let number = 3;

    for (let i = 0; i < arr.length; i++)
    {
        if (typeof arr[i + 1] === undefined)
        {
            arr[0] = arr[i];
        }
        else if (typeof arr[i - 1] === undefined)
        {
            arr[arr.length - 1] = arr[0];
        }
        else
        {
            arr[i] = arr[i + 1];
        }
    }
    console.log(arr);
}
Ivelin Dinev
  • 51
  • 2
  • 8
  • Possible duplicate of [How to access array in circular manner in javascript](http://stackoverflow.com/questions/17483149/how-to-access-array-in-circular-manner-in-javascript) – rlemon Jan 17 '17 at 22:42
  • This is *rotating* the array, not shifting it. – David Conrad Jan 17 '17 at 23:26

5 Answers5

6

This is almost it except it prints [d,e,f ... a,b,c]

for(var i = 0; i < number; i++){
   arr.push(arr.shift());
}

As pointed out in comments do this (thanks @dtkaias): Results in [x,y,z,a,b,c...]

for(var i = 0; i < number; i++){
   arr.unshift(arr.pop());
}

The unshift function adds an element to the front of an array, while the pop function removes the last item, so it moves the last item to the front number times in the loop.

Patrick Murphy
  • 2,311
  • 14
  • 17
4

The tools you're looking for are .slice ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice ), and .concat ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat ).

function getShiftedArray (arr, n) {
    var i = arr.length - n;
    var front = arr.slice(0, i);
    var back = arr.slice(i);
    return back.concat(front);
}
Luke
  • 18,811
  • 16
  • 99
  • 115
1

Here is a solution that copies the result to a new array. Time and space complexity is O(arr.length), if you are looking for a solution that mutates the array in place and has O(x) time complexity then see Patrick's answer.

function rotate(arr, x) {
  return arr.slice(x).concat(arr.slice(0, x));
}

let arr = "abcdefghijkl".split("");

console.log(rotate(arr, -3).join(""));
Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97
1

An invention of Array.prototye.rotate() might come handy for this job. Let's see a simple implementation.

Array.prototype.rotate = function(n) {
                           var len = this.length;
                           return !(n % len) ? this.slice()
                                             : this.map((e,i,a) => a[(i + (len + n % len)) % len]);
                         };

var   alpha = Array(26).fill().map((_,i) => String.fromCharCode(i+97)),
 rotateLeft = e => (alpha = alpha.rotate(1), alphabet.textContent = alpha.join(",")),
rotateRight = e => (alpha = alpha.rotate(-1), alphabet.textContent = alpha.join(","));

alphabet.textContent = alpha.join(",");
buttonLeft.addEventListener("click",rotateLeft);
buttonRight.addEventListener("click",rotateRight);
<div id="alphabet"></div>
<button id="buttonLeft"><<</button>
<button id="buttonRight">>></button>
Redu
  • 25,060
  • 6
  • 56
  • 76
0

Just split the array in 2 parts and concat them afterwards. That's it!

arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
number = 3;

xxx = arr.slice(-number);
yyy = arr.slice(0,arr.length - number);
arr_shift = xxx.concat(yyy);

console.log(arr_shift);
Sascha
  • 4,576
  • 3
  • 13
  • 34