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

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

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

还是c右边的a ?

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

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

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


当前回答

我使用了@Reid这个不错的答案,但是很难将一个元素从数组的末尾移动到开头(就像在循环中一样)。 例如[a, b, c的)应该成为[' c ', ' ', ' b ']通过调用.move(2、3)

我通过改变new_index >= this.length来实现这一点。

Array.prototype.move = function (old_index, new_index) {
        console.log(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) {
            new_index = new_index % this.length;
        }
        this.splice(new_index, 0, this.splice(old_index, 1)[0]);
        return this; // for testing purposes
    };

其他回答

另一个纯JS变体使用ES6数组展开运算符,没有突变

const reorder = (array, sourceIndex, destinationIndex) => { const smallerIndex = Math.min(sourceIndex, destinationIndex); const largerIndex = Math.max(sourceIndex, destinationIndex); return [ ...array.slice(0, smallerIndex), ...(sourceIndex < destinationIndex ? array.slice(smallerIndex + 1, largerIndex + 1) : []), array[sourceIndex], ...(sourceIndex > destinationIndex ? array.slice(smallerIndex, largerIndex) : []), ...array.slice(largerIndex + 1), ]; } // returns ['a', 'c', 'd', 'e', 'b', 'f'] console.log(reorder(['a', 'b', 'c', 'd', 'e', 'f'], 1, 4))

我们可以用多种方法将数组元素从一个位置移动到另一个位置。这里我用三种方法来解决这个问题。

使用拼接移动数组元素,其中时间复杂度为二次time - O(n^2)

function arrayMove(arr, oldIndex, newIndex) {
  const copiedArr = [...arr];
  const length = copiedArr.length;
  
  if (oldIndex !== newIndex && length > oldIndex && length > newIndex) {
    copiedArr.splice(newIndex, 0, copiedArr.splice(oldIndex, 1)[0]);
  }
  
  return copiedArr;
}

arrayMove([1,2,3,4], 0, 3) // [2,3,4,1]

使用flatMap移动数组元素,其中时间复杂度为线性时间- O(n)

function arrayMove(arr, oldIndex, newIndex) {
    const length = arr.length;
    const itemToMove = arr[oldIndex]

    if (oldIndex === newIndex || oldIndex > length || newIndex > length) {
        return arr;
    }

    return arr.flatMap((item, index) => {
        if (index === oldIndex) return [];
        if (index === newIndex) return oldIndex < newIndex ? [item, itemToMove] : [itemToMove, item];
        return item;
    })
}

arrayMove([1,2,3,4], 0, 3) // [2,3,4,1]

当时间复杂度为线性时间- O(n)时,使用reduce方法移动数组元素

function arrayMove(arr, oldIndex, newIndex) {
    const length = arr.length;
    const itemToMove = arr[oldIndex]

    if (oldIndex === newIndex || oldIndex > length || newIndex > length) {
        return arr;
    }

    return arr.reduce((acc, item, index) => {
        if (index === oldIndex) return acc;
        if (index === newIndex) return oldIndex < newIndex ? [...acc, item, itemToMove] : [...acc, itemToMove, item];
        return [...acc, item];
    }, [])
}

arrayMove([1,2,3,4], 0, 3) // [2,3,4,1]

您还可以检查以下要点:将数组元素从一个数组位置移动到另一个数组位置

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

对于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

Array的splice方法可能有帮助:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice

请记住,它可能相对昂贵,因为它必须主动重新索引数组。

我需要一个不可变的移动方法(一个不改变原始数组的方法),所以我改编了@Reid的接受的答案,简单地使用对象。赋值以在进行拼接之前创建数组的副本。

Array.prototype.immutableMove = function (old_index, new_index) {
  var copy = Object.assign([], this);
  if (new_index >= copy.length) {
      var k = new_index - copy.length;
      while ((k--) + 1) {
          copy.push(undefined);
      }
  }
  copy.splice(new_index, 0, copy.splice(old_index, 1)[0]);
  return copy;
};

下面是一个jsfiddle演示它的运行。