Move Array Element
Prompt
/**
* Write a function to move an array element from one position to another.
*
* Examples:
*
* console.log(move([10, 20, 30, 40, 50], 0, 2));
* [20, 30, 10, 40, 50]
*
* console.log(move([10, 20, 30, 40, 50], -1, -2));
* [10, 20, 50, 30, 40]
*
*/
function move(arr, pos, shift) {
// Some magic here
return arr;
}
console.log(move([10, 20, 30, 40, 50], 0, 2));Playground
The first thing you need to handle is negative indices. If pos is negative, you'll need to convert it to a positive index. Think about how you can use the array's length to do this. For example, if pos is -1 and the array has 5 elements, the actual index would be 5 + (-1) = 4.
To move an element, you'll need to do two things: first, remove the element from its current position, and second, insert it at the new position. The splice() method is perfect for both of these operations - it can remove elements and also insert elements at a specific index.
When calculating the new position, simply add the shift to the current position. But be careful - you might need to handle cases where the new position goes out of bounds. Consider what should happen if the new position is negative or greater than the array length.
Solution
Explanation
This problem looks simple at first glance, but there are a few tricky parts to handle. Let's break it down step by step.
Handling Negative Indices
The first challenge is dealing with negative indices. In JavaScript, arrays don't natively support negative indexing like Python does. So we need to convert negative indices to their positive equivalents:
let fromIndex = pos < 0 ? length + pos : pos;If pos is -1 and the array has 5 elements, this gives us 5 + (-1) = 4, which is the index of the last element. Simple math, but easy to forget!
Calculating the New Position
Next, we figure out where the element should end up:
let toIndex = fromIndex + shift;But wait - what if toIndex ends up being negative or larger than the array length? We need to wrap it around:
toIndex = ((toIndex % length) + length) % length;This formula might look a bit intimidating, but it's a common pattern for handling wrap-around. The double modulo operation ensures the result is always positive and within bounds.
The Actual Move
Now for the fun part - actually moving the element. We use splice() twice:
-
Remove the element:
arr.splice(fromIndex, 1)removes one element atfromIndexand returns it as an array. We use destructuring[element]to grab the actual value. -
Insert at new position:
arr.splice(toIndex, 0, element)inserts the element attoIndexwithout removing anything (that's what the0is for).
const [element] = arr.splice(fromIndex, 1);
arr.splice(toIndex, 0, element);Why This Works
The beauty of this solution is that splice() handles all the heavy lifting. When you remove an element, the array automatically shifts to fill the gap. When you insert, everything shifts to make room. We're just telling the array where to remove from and where to insert to.
Dry Run
Let's walk through move([10, 20, 30, 40, 50], -1, -2):
- Initial array:
[10, 20, 30, 40, 50], length = 5 - Convert negative index:
pos = -1→fromIndex = 5 + (-1) = 4 - Calculate new position:
toIndex = 4 + (-2) = 2 - Remove element: We remove
50from index 4 → array becomes[10, 20, 30, 40] - Insert element: We insert
50at index 2 → array becomes[10, 20, 50, 30, 40] - Result:
[10, 20, 50, 30, 40]
Notes
The Double Modulo Trick
You might wonder why we use ((toIndex % length) + length) % length instead of just toIndex % length.
The issue is that in JavaScript, the modulo operator % can return negative numbers. For example, -1 % 5 returns -1, not 4.
By adding length and taking modulo again, we ensure the result is always positive:
-1 % 5=-1(-1 + 5) % 5=4 % 5=4
This is a handy trick to remember whenever you need wrap-around behavior!
Splice Returns an Array
A common gotcha with splice() is that it returns an array of removed elements, not a single element. That's why we use array destructuring:
const [element] = arr.splice(fromIndex, 1);If we just did const element = arr.splice(fromIndex, 1), we'd get [50] instead of 50.