Change elements positions in an array and shift elements in between

Take a look at this method: Array.prototype.copyWithin().

There is a more efficient in-place way to do it:

function insertAndShift(data, src, dest) {
    if (src === dest)
        return;

    let tmp = data[src];
    if (src < dest) {
        data.copyWithin(src, src + 1, dest + 1);
    } else /* if (src > dest) */ {
        data.copyWithin(dest + 1, dest, src);
    }
    data[dest] = tmp;
}

let data = [0, 1, 2, 3, 4, 5, 6];

insertAndShift(data, 0, 3);
console.log("[" + data + "]");

insertAndShift(data, 3, 0);
console.log("[" + data + "]");

Below is an illustration:

Case 1 (src < dest):
[..Sabcd..]
    ////       // data.copyWithin(src, src+1, dest+1);
[..abcdd..]
[..abcdS..]    // data[dest] = tmp;

Case 2 (src > dest):
[..abcdS..]
    \\\\       // data.copyWithin(dest+1, dest, src);
[..aabcd..]
[..Sabcd..]    // data[dest] = tmp;

The answer above works great but it's a little handwavy... if you are interested in a solution that spells out what it's doing I wrote this:

const insertAndShift = (arr: number[], to: number, from: number) => {
  let newArray: number[] = [];
  const fromItem = arr[from];
  if (from > to) {
    const startToTo = (to > 0) ? arr.slice(0, to) : [];
    const toToFrom = arr.slice(to, from);
    const fromToEnd = arr.slice(from + 1, arr.length);
    newArray = newArray.concat(startToTo, [fromItem], toToFrom, fromToEnd);
  }
  if (to > from) {
    const startToFrom = (from > 0) ? arr.slice(0, from) : [];
    const fromToTo = arr.slice(from + 1, to + 1);
    const toToEnd = arr.slice(to + 1, arr.length);
    newArray = newArray.concat(startToFrom, fromToTo, fromItem, toToEnd);
  }
  return newArray;
};

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

console.log(insertAndShift(array, 9, 0));
console.log(insertAndShift(array, 5, 1));

You can use Array.prototype.splice to cut out the element you want and insert at the desired index (the shifting will happen automatically):

function insertAndShift(arr, from, to) {
    let cutOut = arr.splice(from, 1) [0]; // cut the element at index 'from'
    arr.splice(to, 0, cutOut);            // insert it at index 'to'
}



let data = [ 0, 1, 2, 3, 4, 5, 6 ];

insertAndShift(data, 0, 3);
console.log("[" + data + "]");

insertAndShift(data, 3, 0);
console.log("[" + data + "]");