我很难弄清楚如何移动数组元素。例如,给定以下内容:
var arr = [ 'a', 'b', 'c', 'd', 'e'];
我怎样才能写一个函数来移动'd'之前'b'?
还是'a'之后'c'?
移动后,应更新其余元素的索引。这意味着在移动后的第一个示例中,
arr = ['a', 'd', 'b', 'c', 'e']
这看起来应该很简单,但我无法理解它。
我很难弄清楚如何移动数组元素。例如,给定以下内容:
var arr = [ 'a', 'b', 'c', 'd', 'e'];
我怎样才能写一个函数来移动'd'之前'b'?
还是'a'之后'c'?
移动后,应更新其余元素的索引。这意味着在移动后的第一个示例中,
arr = ['a', 'd', 'b', 'c', 'e']
这看起来应该很简单,但我无法理解它。
如果你想要 npm 上的一个版本,array-move是最接近这个答案的,尽管它不是相同的实现。有关更多详细信息,请参阅其用法部分。可以在 npm 上的array.prototype.move上找到此答案的先前版本(修改后的 Array.prototype.move)。
我在这个功能上取得了相当不错的成功:
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.
逐步执行代码:
new_index大于数组的长度,我们希望(我假设)用 new undefineds正确填充数组。这个小片段通过推动undefined数组直到我们有合适的长度来处理这个问题。arr.splice(old_index, 1)[0],我们拼接出旧元素。splice返回拼接出来的元素,但它在一个数组中。在我们上面的例子中,这是[1]. 因此,我们采用该数组的第一个索引来获取原始数据1。splice在new_index 的地方插入这个元素。因为我们在 if 上面填充了数组new_index > arr.length,它可能会出现在正确的位置,除非他们做了一些奇怪的事情,比如传入一个负数。一个更高级的版本来解释负指数:
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]。
无论哪种方式,在您最初的问题中,您都会array_move(arr, 0, 2)为aafter做c。对于d以前b,你会这样做array_move(arr, 3, 1)。
我喜欢这种方式。它简洁且有效。
function arraymove(arr, fromIndex, toIndex) {
    var element = arr[fromIndex];
    arr.splice(fromIndex, 1);
    arr.splice(toIndex, 0, element);
}
注意:永远记得检查你的数组边界。
这是我在 JSPerf 上找到的一个班轮......
Array.prototype.move = function(from, to) {
    this.splice(to, 0, this.splice(from, 1)[0]);
};
读起来很棒,但是如果您想要性能(在小数据集中),请尝试...
 Array.prototype.move2 = function(pos1, pos2) {
    // local variables
    var i, tmp;
    // cast input parameters to integers
    pos1 = parseInt(pos1, 10);
    pos2 = parseInt(pos2, 10);
    // if positions are different and inside array
    if (pos1 !== pos2 && 0 <= pos1 && pos1 <= this.length && 0 <= pos2 && pos2 <= this.length) {
      // save element from position 1
      tmp = this[pos1];
      // move element down and shift other elements up
      if (pos1 < pos2) {
        for (i = pos1; i < pos2; i++) {
          this[i] = this[i + 1];
        }
      }
      // move element up and shift other elements down
      else {
        for (i = pos1; i > pos2; i--) {
          this[i] = this[i - 1];
        }
      }
      // put element from position 1 to destination
      this[pos2] = tmp;
    }
  }
我不能相信任何功劳,这一切都应该归功于理查德·斯卡洛特。在这个性能测试中,它在较小的数据集上击败了基于拼接的方法。然而,正如 Darwayne 指出的那样,它在较大的数据集上要慢得多。
splice() 方法向/从数组添加/删除项目,并返回删除的项目。
注意:此方法更改原始数组。/w3学校/
Array.prototype.move = function(from,to){
  this.splice(to,0,this.splice(from,1)[0]);
  return this;
};
var arr = [ 'a', 'b', 'c', 'd', 'e'];
arr.move(3,1);//["a", "d", "b", "c", "e"]
var arr = [ 'a', 'b', 'c', 'd', 'e'];
arr.move(0,2);//["b", "c", "a", "d", "e"]
由于该功能是可链接的,因此也可以使用:
alert(arr.move(0,2).join(','));
我的 2c 易于阅读,有效,速度快,不会创建新数组。
function move(array, from, to) {
  if( to === from ) return array;
  var target = array[from];                         
  var increment = to < from ? -1 : 1;
  for(var k = from; k != to; k += increment){
    array[k] = array[k + increment];
  }
  array[to] = target;
  return array;
}