我很难弄清楚如何移动数组中的一个元素。例如,给定以下条件:

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

我怎么能写一个函数来移动元素'd'到'b'的左边?

还是c右边的a ?

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

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

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


当前回答

下面是我的一行ES6解决方案,带有一个可选参数。

if (typeof Array.prototype.move === "undefined") {
  Array.prototype.move = function(from, to, on = 1) {
    this.splice(to, 0, ...this.splice(from, on))
  }
}

digiguru提出的第一个解决方案的改编

on的参数是你想要移动的元素个数。

这里有一个可链接的变化:

if (typeof Array.prototype.move === "undefined") {
  Array.prototype.move = function(from, to, on = 1) {
    return this.splice(to, 0, ...this.splice(from, on)), this
  }
}

[3, 4, 5, 1, 2].move(3, 0, 2) // => [1, 2, 3, 4, 5]

如果你想避免原型污染,这里有一个独立的函数:

function move(array, from, to, on = 1) {
  return array.splice(to, 0, ...array.splice(from, on)), array
}

move([3, 4, 5, 1, 2], 3, 0, 2) // => [1, 2, 3, 4, 5]

最后,这是一个不会改变原始数组的纯函数:

function moved(array, from, to, on = 1) {
  return array = array.slice(), array.splice(to, 0, ...array.splice(from, on)), array
}

这应该涵盖了其他答案中出现的所有变化。

其他回答

我的2摄氏度。易读,有效,快速,不需要创建新数组。

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;
}

这个版本并不适合所有目的,也不是每个人都喜欢逗号表达式,但这里有一个纯表达式,创建了一个新的副本:

const move = (from, to, ...a) => (a.splice(to, 0, ...a.splice(from, 1)), a)

性能略有改进的版本在不需要移动的情况下返回输入数组,它仍然可以用于不可变的用途,因为数组不会改变,并且它仍然是一个纯表达式:

const move = (from, to, ...a) => 
    from === to 
    ? a 
    : (a.splice(to, 0, ...a.splice(from, 1)), a)

两者的调用都是

const shuffled = move(fromIndex, toIndex, ...list)

也就是说,它依靠传播来产生一个新的副本。使用固定值3的移动会危及单个表达式的属性,或非破坏性的性质,或拼接的性能优势。同样,它更像是一个满足某些标准的示例,而不是供生产使用的建议。

就像所有事情一样,充分利用是最重要的。

对于单个移动,以及小型和大型数据集,这里都有完美的答案。 如果你正在做成千上万的移动,我建议你看看状态和不太频繁的密集操作。喜欢的东西:

改变你的数据集,保持对每个项目的订单“状态”。 应用数以千计的更新。 对该order属性执行单一排序。

 ["a", "b", "c"]

会改为

[
   {val: 'a', order: 0},
   {val: 'b', order: 1},
   {val: 'c', order: 2},

]

然后,应用数千次更新。

最后,根据“order”变量进行排序。 也许还要重新编号。

我还没有测试它的性能,但是可以想象,在一定的使用水平上,它比每1000次重新构建数组要好得多。

这是一个非常简单的使用拼接的方法

Array.prototype.moveToStart = function(index) {
    this.splice(0, 0, this.splice(index, 1)[0]);
    return this;
  };

您可以实现一些基本的演算,并创建一个通用函数来将数组元素从一个位置移动到另一个位置。

对于JavaScript,它看起来是这样的:

function magicFunction (targetArray, indexFrom, indexTo) { 

    targetElement = targetArray[indexFrom]; 
    magicIncrement = (indexTo - indexFrom) / Math.abs (indexTo - indexFrom); 

    for (Element = indexFrom; Element != indexTo; Element += magicIncrement){ 
        targetArray[Element] = targetArray[Element + magicIncrement]; 
    } 

    targetArray[indexTo] = targetElement; 

}

查看“移动数组元素”在“忧郁”的详细解释。

https://web.archive.org/web/20121105042534/http://www.gloommatter.com:80/DDesign/programming/moving-any-array-elements-universal-function.html