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 + "]");