我很难弄清楚如何移动数组中的一个元素。例如,给定以下条件:
var array = [ 'a', 'b', 'c', 'd', 'e'];
我怎么能写一个函数来移动元素'd'到'b'的左边?
还是c右边的a ?
移动元素之后,应该更新其余元素的索引。结果数组将是:
array = ['a', 'd', 'b', 'c', 'e']
这看起来应该很简单,但我无法理解它。
我很难弄清楚如何移动数组中的一个元素。例如,给定以下条件:
var array = [ 'a', 'b', 'c', 'd', 'e'];
我怎么能写一个函数来移动元素'd'到'b'的左边?
还是c右边的a ?
移动元素之后,应该更新其余元素的索引。结果数组将是:
array = ['a', 'd', 'b', 'c', 'e']
这看起来应该很简单,但我无法理解它。
当前回答
就像所有事情一样,充分利用是最重要的。
对于单个移动,以及小型和大型数据集,这里都有完美的答案。 如果你正在做成千上万的移动,我建议你看看状态和不太频繁的密集操作。喜欢的东西:
改变你的数据集,保持对每个项目的订单“状态”。 应用数以千计的更新。 对该order属性执行单一排序。
["a", "b", "c"]
会改为
[
{val: 'a', order: 0},
{val: 'b', order: 1},
{val: 'c', order: 2},
]
然后,应用数千次更新。
最后,根据“order”变量进行排序。 也许还要重新编号。
我还没有测试它的性能,但是可以想象,在一定的使用水平上,它比每1000次重新构建数组要好得多。
其他回答
我的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;
}
我需要一个不可变的移动方法(一个不改变原始数组的方法),所以我改编了@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演示它的运行。
就像所有事情一样,充分利用是最重要的。
对于单个移动,以及小型和大型数据集,这里都有完美的答案。 如果你正在做成千上万的移动,我建议你看看状态和不太频繁的密集操作。喜欢的东西:
改变你的数据集,保持对每个项目的订单“状态”。 应用数以千计的更新。 对该order属性执行单一排序。
["a", "b", "c"]
会改为
[
{val: 'a', order: 0},
{val: 'b', order: 1},
{val: 'c', order: 2},
]
然后,应用数千次更新。
最后,根据“order”变量进行排序。 也许还要重新编号。
我还没有测试它的性能,但是可以想象,在一定的使用水平上,它比每1000次重新构建数组要好得多。
我已经实现了一个不可变的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;
};
变量名可以缩短,只使用长变量名,这样代码就可以解释自己。
我喜欢这样。它简洁而有效。
function arraymove(arr, fromIndex, toIndex) {
var element = arr[fromIndex];
arr.splice(fromIndex, 1);
arr.splice(toIndex, 0, element);
}
注意:总是记得检查你的数组边界。
在jsFiddle中运行Snippet