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

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

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

还是c右边的a ?

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

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

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


当前回答

我已经实现了一个不可变的ECMAScript 6解决方案,基于@Merc的答案在这里:

const moveItemInArrayFromIndexToIndex = (array, fromIndex, toIndex) => {
  if (fromIndex === toIndex) return array;

  const newArray = [...array];

  const target = newArray[fromIndex];
  const inc = toIndex < fromIndex ? -1 : 1;

  for (let i = fromIndex; i !== toIndex; i += inc) {
    newArray[i] = newArray[i + inc];
  }

  newArray[toIndex] = target;

  return newArray;
};

变量名可以缩短,只使用长变量名,这样代码就可以解释自己。

其他回答

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

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

打印稿版本

摘自@Merc的回答。我最喜欢这个,因为它没有创建新的数组,而是在适当的地方修改数组。我所做的只是更新到ES6并添加类型。

export function moveItemInArray<T>(workArray: T[], fromIndex: number, toIndex: number): T[] {
    if (toIndex === fromIndex) {
        return workArray;
    }
    const target = workArray[fromIndex];
    const increment = toIndex < fromIndex ? -1 : 1;

    for (let k = fromIndex; k !== toIndex; k += increment) {
        workArray[k] = workArray[k + increment];
    }
    workArray[toIndex] = target;
    return workArray;
}

这里有一种方法可以用不变的方式来做。它处理负数以及一个额外的奖励。与编辑原始数组相比,这以性能为代价减少了可能的错误数量。

const numbers = [1, 2, 3];
const moveElement = (array, from, to) => {
  const copy = [...array];
  const valueToMove = copy.splice(from, 1)[0];
  copy.splice(to, 0, valueToMove);
  return copy;
};

console.log(moveElement(numbers, 0, 2))
// > [2, 3, 1]
console.log(moveElement(numbers, -1, -3))
// > [3, 1, 2] 

我的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, 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}