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

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

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

还是c右边的a ?

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

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

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


当前回答

如果对象是嵌套的:

  let array = ['a', 'b', 'c', 'd', 'e'];
  let existingElement = JSON.parse(JSON.stringify(array[3]));
  array.splice(1, 0, existingElement);
  array.splice(4, 1);
  console.log(array)

其他回答

从@Reid得到这个想法,在应该被移动的项目的地方推动一些东西,以保持数组大小不变。这确实简化了计算。此外,推入空对象还有一个额外的好处,就是以后能够惟一地搜索它。这是因为两个对象在引用同一个对象之前是不相等的。

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

这个函数接收源数组,以及源和目标索引。你可以把它添加到数组中。原型(如果需要的话)。

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

如果对象是嵌套的:

  let array = ['a', 'b', 'c', 'd', 'e'];
  let existingElement = JSON.parse(JSON.stringify(array[3]));
  array.splice(1, 0, existingElement);
  array.splice(4, 1);
  console.log(array)

下面是我在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指出的那样,在较大的数据集上,它要慢得多。

该方法将保留原始数组,并检查边界错误。

const move = (from, to, arr) => {
    to = Math.max(to,0)
    from > to 
        ? [].concat(
            arr.slice(0,to), 
            arr[from], 
            arr.filter((x,i) => i != from).slice(to)) 
        : to > from
            ? [].concat(
                arr.slice(0, from), 
                arr.slice(from + 1, to + 1), 
                arr[from], 
                arr.slice(to + 1))
            : arr}

我喜欢不可变的,函数式的语句:)…

const swapIndex = (array, from, to) => (
  from < to 
    ? [...array.slice(0, from), ...array.slice(from + 1, to + 1), array[from], ...array.slice(to + 1)] 
    : [...array.slice(0, to), array[from], ...array.slice(to, from), ...array.slice(from + 1)]
);