我有一段时间,搞清楚如何移动数组元素。例如,假设有以下示例︰

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

如何编写一个函数来移动'd' 'b'之前?

'a'之后'c'?

移动之后,应更新其余的元素的索引。之后将 = 移动 arr [0],这意味着在第一个示例 [1] 'a',arr = 有 arr [2] = 'b',arr [3] = c,[4] arr = 'e'

这似乎是它应该是非常简单,但我不能换我的头在其周围。

2011-03-15 01:57:45
问题评论:

回答:

我有很好成功与此函数︰

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

示例代码︰ [1, 2, 3].move(0, 1)提供[2, 1, 3].

请注意,return的最后一个仅用于测试目的︰splice的运算在数组中的位置,因此不需要回报。引申一下,此move是就地操作。如果您想要避免的并返回一个副本,使用slice.

逐句通过代码︰

  1. 如果数组的长度大于new_index ,我们希望 (我以为) 填充正确与新的undefineds 的数组。此小代码段处理这按undefined阵列上直到我们有适当的长度。
  2. 然后,在this.splice(old_index, 1)[0],我们拼接出旧的元素。splice返回的元素是拼接出,但在一个数组中。在上面的示例中,这就是[1]因此,我们采取以获取原始1那里该数组的第一个索引。
  3. 然后我们使用splice在 new_index 的位置插入该元素。因为我们填补上述数组new_index > this.length,它将可能出现在正确的位置,除非他们已经完成了一些奇怪的东西像负数传入。

考虑到负索引更别致版本︰

Array.prototype.move = function (old_index, new_index) {
    while (old_index < 0) {
        old_index += this.length;
    }
    while (new_index < 0) {
        new_index += this.length;
    }
    if (new_index >= this.length) {
        var k = new_index - this.length;
        while ((k--) + 1) {
            this.push(undefined);
        }
    }
    this.splice(new_index, 0, this.splice(old_index, 1)[0]);
    return this; // for testing purposes
};

它应考虑如下事物[1, 2, 3, 4, 5].move(-1, -2)正确 (移至第二行到最后位置的最后一个元素)。该结果应为[1, 2, 3, 5, 4].

ChillyPenguin已上载到 npm 方便安装的此版本︰ https://www.npmjs.com/package/array.prototype.move ChillyPenguin,谢谢 !

无论如何,您原始的问题,做为a arr.move(0, 2) c之后。对于d b之前,您将执行arr.move(3, 1).

这工作完全正常 !和您的说明是十分清楚。感谢您花费时间来编写这。

您不应操纵对象和数组的原型,循环元素时导致问题。

@burakemre︰ 我认为很明显未达到该结论。大多数好的 JS 程序员 (和最受欢迎的库) 将使用.hasOwnProperty检查时循环使用的诸如...在特别是与像原型和 MooTools 库的修改原型。不管怎样,我不感觉它是一个相对有限的例子这样,特别重要的问题,并且通过原型修改是一个好主意没有好社区中的剥离。通常情况下,迭代问题不过是最关心的问题。

没有必要为在步骤 1 中的循环,您可以直接使用this[new_index] = undefined; if块中。因为 Javascript 数组是稀疏的这将延长包括 new_index .splice工作,但不需要创建任何插入的元素的数组大小。

@Michael︰ 好点-但这样做this[new_index] = undefined实际投入undefined数组中将插槽正确的索引。(例如, [1,2,3].move(0,10)将有槽 9 1 10 插槽中并undefined。)相反,sparseness 是确定,是否能做到this[new_index] = this.splice(old_index, 1)[0]不拼接调用 (使其相反如果/其他)。

这里是我在 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;
    }
  }

我不能得到任何信用卡,都得给理查德 • Scarrott这一点在性能测试此领先数据集较小的基于接合方法。很明显但是慢上较大的数据将设置为 Darwayne 指出.

此 move2 方法很好,因为它允许移动向上或向下数组的数组元素。我遇到了问题,与一些其他解决方案时向右移动数组元素。

更多性能解决方案较慢对大型数据集。jsperf.com/array-prototype-move/8

这似乎是非常愚蠢的 tradeof。小数据集上的性能是可以忽略不计的收益,但在大型数据集上的损失是重大的损失。您净交换是负的。

单行式命令很好,但是不能处理移动超出数组结尾的元素。

不是要求的 @Reid。IMO 是可以假定该数组的长度不被修改。

我喜欢这种方式。它的工作原理,它是快速的和典雅。

function arraymove(arr, fromIndex, toIndex) {
    var element = arr[fromIndex];
    arr.splice(fromIndex, 1);
    arr.splice(toIndex, 0, element);
}

注意︰ 始终记住检查数组界限。

index1 吗?你的意思是 fromIndex?

由于 Array.splice 在一个新的数组中返回已删除的值,您可以将其保存为一套...arr.splice (索引 + 1,0,arr.splice (索引、 1)[0]);

非常干净的代码感谢的

haha steak 溢出 haha

从 @Reid 的推东西应该被移动以使数组大小不变的项替换了这一思想。该 does 简化计算。另外,推一个空对象有能够唯一地在以后对其进行搜索其他的优点。这样做的原因有两个对象相等,直到他们都引用同一个对象。

({}) == ({}); // false

这是将源数组和源,目标索引中的函数。您可以将其添加到 Array.prototype,如果需要。

function moveObjectAtIndex(array, sourceIndex, destIndex) {
    var placeholder = {};
    // remove the object from its initial position and
    // plant the placeholder object in its place to
    // keep the array length constant
    var objectToMove = array.splice(sourceIndex, 1, placeholder)[0];
    // place the object in the desired position
    array.splice(destIndex, 0, objectToMove);
    // take out the temporary object
    array.splice(array.indexOf(placeholder), 1);
}

这看来大有希望...,我不知道,关于 javascript js 比较。谢谢 !

Splice () 方法添加/删除项到从一个数组中,并返回所移除的项目。

注意︰ 此方法更改原始数组。/w3schools/

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(','));

此处的演示

我喜欢,我的工作。

请输入您的翻译

Move an array element from one array position to another

确认取消