将数组元素从一个数组位置移动到另一个位置

2022-01-31 00:00:00 arrays javascript

我很难弄清楚如何移动数组的元素.例如,给定以下内容:

I'm having a hard time figuring out how to move an element of an array. For example, given the following:

var array = [ 'a', 'b', 'c', 'd', 'e'];

如何编写函数将元素 'd' 移动到 'b' 的左侧?

How can I write a function to move the element 'd' to the left of 'b' ?

或者'c'右边的'a'?

移动元素后,应该更新其余元素的索引.结果数组将是:

After moving the elements, the indexes of the rest of the elements should be updated. The resulting array would be:

array = ['a', 'd', 'b', 'c', 'e']

这看起来应该很简单,但我无法理解它.

This seems like it should be pretty simple, but I can't wrap my head around it.

推荐答案

如果你想要 npm 上的版本,array-move 是最接近这个答案的,尽管它不是同一个实现.有关更多详细信息,请参阅其用法部分.可以在 npm 的 上找到此答案的先前版本(修改后的 Array.prototype.move)array.prototype.move.

If you'd like a version on npm, array-move is the closest to this answer, although it's not the same implementation. See its usage section for more details. The previous version of this answer (that modified Array.prototype.move) can be found on npm at array.prototype.move.

我在这个功能上取得了相当大的成功:

I had fairly good success with this function:

function array_move(arr, old_index, new_index) {
    if (new_index >= arr.length) {
        var k = new_index - arr.length + 1;
        while (k--) {
            arr.push(undefined);
        }
    }
    arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
    return arr; // for testing
};

// returns [2, 1, 3]
console.log(array_move([1, 2, 3], 0, 1)); 

请注意,最后一个 return 仅用于测试目的:splice 就地对数组执行操作,因此不需要返回.通过扩展,这个 move 是一个就地操作.如果您想避免这种情况并返回副本,请使用 slice.

Note that the last return is simply for testing purposes: splice performs operations on the array in-place, so a return is not necessary. By extension, this move is an in-place operation. If you want to avoid that and return a copy, use slice.

单步执行代码:

  1. 如果 new_index 大于数组的长度,我们希望(我假设)用新的 undefined 正确填充数组.这个小片段通过将 undefined 推送到数组上来处理这个问题,直到我们获得适当的长度.
  2. 然后,在 arr.splice(old_index, 1)[0] 中,我们拼接出旧元素.splice 返回被拼接出来的元素,但它在一个数组中.在我们上面的例子中,这是 [1].所以我们使用该数组的第一个索引来获取原始 1 那里.
  3. 然后我们使用 splice 将这个元素插入到 new_index 的位置.因为我们填充了上面的数组 if new_index >arr.length,它可能会出现在正确的位置,除非他们做了一些奇怪的事情,比如传入一个负数.
  1. If new_index is greater than the length of the array, we want (I presume) to pad the array properly with new undefineds. This little snippet handles this by pushing undefined on the array until we have the proper length.
  2. Then, in arr.splice(old_index, 1)[0], we splice out the old element. splice returns the element that was spliced out, but it's in an array. In our above example, this was [1]. So we take the first index of that array to get the raw 1 there.
  3. Then we use splice to insert this element in the new_index's place. Since we padded the array above if new_index > arr.length, it will probably appear in the right place, unless they've done something strange like pass in a negative number.

一个更好的版本来解释负指数:

A fancier version to account for negative indices:

function array_move(arr, old_index, new_index) {
    while (old_index < 0) {
        old_index += arr.length;
    }
    while (new_index < 0) {
        new_index += arr.length;
    }
    if (new_index >= arr.length) {
        var k = new_index - arr.length + 1;
        while (k--) {
            arr.push(undefined);
        }
    }
    arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
    return arr; // for testing purposes
};
    
// returns [1, 3, 2]
console.log(array_move([1, 2, 3], -1, -2));

这应该正确考虑 array_move([1, 2, 3], -1, -2) 之类的事情(将最后一个元素移动到倒数第二个位置).结果应该是 [1, 3, 2].

Which should account for things like array_move([1, 2, 3], -1, -2) properly (move the last element to the second to last place). Result for that should be [1, 3, 2].

无论哪种方式,在您最初的问题中,您都会在 c 之后为 a 执行 array_move(arr, 0, 2).对于 b 之前的 d,您将执行 array_move(arr, 3, 1).

Either way, in your original question, you would do array_move(arr, 0, 2) for a after c. For d before b, you would do array_move(arr, 3, 1).

相关文章