Mar*_*own 464 javascript arrays
我很难搞清楚如何移动数组元素.例如,给出以下内容:
var arr = [ 'a', 'b', 'c', 'd', 'e'];
Run Code Online (Sandbox Code Playgroud)
我怎么能写一个'd'
以前移动的函数'b'
?
还是'a'
之后'c'
?
移动后,应更新其余元素的索引.这意味着在第一个例子中,移动arr [0]将='a',arr [1] ='d'arr [2] ='b',arr [3] ='c',arr [4] = 'E'
这看起来应该很简单,但我无法绕过它.
Rei*_*eid 630
如果您想在npm上使用某个版本,则array-move最接近此答案,尽管它的实现并不相同.有关详细信息,请参阅其用法部分.可以在array.prototype.move的 npm上找到此答案的先前版本(修改后的Array.prototype.move).
我在这个功能上取得了相当不错的成功:
function array_move(arr, old_index, new_index) {
if (new_index >= arr.length) {
var k = new_index - arr.length + 1;
while (k--) {
arr.push(undefined);
}
}
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
return arr; // for testing
};
// returns [2, 1, 3]
console.log(array_move([1, 2, 3], 0, 1));
Run Code Online (Sandbox Code Playgroud)
请注意,最后一个return
仅用于测试目的:splice
就地对阵列执行操作,因此不需要返回.通过扩展,这move
是一个就地操作.如果您想避免这种情况并返回副本,请使用slice
.
单步执行代码:
new_index
大于数组的长度,我们希望(我推测)用新的undefined
s 正确填充数组.这个小片段通过推动undefined
阵列来处理这个问题,直到我们有适当的长度.arr.splice(old_index, 1)[0]
,我们拼出旧元素.splice
返回拼接出来的元素,但它在一个数组中.在上面的例子中,这是[1]
.所以我们采用该数组的第一个索引来获取原始数据1
.splice
这个元素插入new_index的位置.因为我们填充了上面的数组,如果new_index > arr.length
它,它可能会出现在正确的位置,除非他们做了一些奇怪的事情,如传递负数.一个代表负面指数的发烧友版本:
function array_move(arr, old_index, new_index) {
while (old_index < 0) {
old_index += arr.length;
}
while (new_index < 0) {
new_index += arr.length;
}
if (new_index >= arr.length) {
var k = new_index - arr.length + 1;
while (k--) {
arr.push(undefined);
}
}
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
return arr; // for testing purposes
};
// returns [1, 3, 2]
console.log(array_move([1, 2, 3], -1, -2));
Run Code Online (Sandbox Code Playgroud)
哪个应该考虑到array_move([1, 2, 3], -1, -2)
正确的事情(将最后一个元素移动到倒数第二个位置).结果应该是[1, 3, 2]
.
无论哪种方式,在你原来的问题,你会怎么做array_move(arr, 0, 2)
了a
之后c
.对于d
之前b
,你会怎么做array_move(arr, 3, 1)
.
dig*_*uru 252
这是我在JSPerf上发现的一个内容....
Array.prototype.move = function(from, to) {
this.splice(to, 0, this.splice(from, 1)[0]);
};
Run Code Online (Sandbox Code Playgroud)
这是很棒的阅读,但如果你想要性能(在小数据集中)尝试...
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;
}
}
Run Code Online (Sandbox Code Playgroud)
我不能相信,它应该全部归Richard Scarrott所有.它在此性能测试中击败了基于拼接的方法,用于较小的数据集.然而Darwayne指出,在较大的数据集上,它会明显变慢.
Ste*_*low 184
我喜欢这种方式.它有效,简洁而优雅.
function arraymove(arr, fromIndex, toIndex) {
var element = arr[fromIndex];
arr.splice(fromIndex, 1);
arr.splice(toIndex, 0, element);
}
Run Code Online (Sandbox Code Playgroud)
注意:请记住检查数组边界.
这是一个测试的jsFiddle:https://jsfiddle.net/aq9Laaew/286055/
小智 33
splice()方法向/从数组添加/删除项,并返回已删除的项.
注意:此方法更改原始数组./ W3Schools的/
Array.prototype.move = function(from,to){
this.splice(to,0,this.splice(from,1)[0]);
return this;
};
var arr = [ 'a', 'b', 'c', 'd', 'e'];
arr.move(3,1);//["a", "d", "b", "c", "e"]
var arr = [ 'a', 'b', 'c', 'd', 'e'];
arr.move(0,2);//["b", "c", "a", "d", "e"]
Run Code Online (Sandbox Code Playgroud)
由于该功能是可链接的,因此也适用:
alert(arr.move(0,2).join(','));
Run Code Online (Sandbox Code Playgroud)
Mer*_*erc 26
我的2c.易于阅读,有效,速度快,无法创建新阵列.
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;
}
Run Code Online (Sandbox Code Playgroud)
Anu*_*rag 16
从@Reid那里得到了这个想法,即在应该移动的项目的位置推送一些东西来保持数组大小不变.这确实简化了计算.此外,推送空对象还具有以后能够唯一地搜索它的好处.这是有效的,因为两个对象在引用同一对象之前不相等.
({}) == ({}); // false
Run Code Online (Sandbox Code Playgroud)
所以这里是接收源数组的函数,以及源,目标索引.如果需要,您可以将它添加到Array.prototype.
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);
}
Run Code Online (Sandbox Code Playgroud)
And*_*ena 15
这是基于@ Reid的解决方案.除了:
Array
原型.undefined
项目,它只是将项目移动到最右侧的位置.功能:
function move(array, oldIndex, newIndex) {
if (newIndex >= array.length) {
newIndex = array.length - 1;
}
array.splice(newIndex, 0, array.splice(oldIndex, 1)[0]);
return array;
}
Run Code Online (Sandbox Code Playgroud)
单元测试:
describe('ArrayHelper', function () {
it('Move right', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 0, 1);
assert.equal(array[0], 2);
assert.equal(array[1], 1);
assert.equal(array[2], 3);
})
it('Move left', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 1, 0);
assert.equal(array[0], 2);
assert.equal(array[1], 1);
assert.equal(array[2], 3);
});
it('Move out of bounds to the left', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 1, -2);
assert.equal(array[0], 2);
assert.equal(array[1], 1);
assert.equal(array[2], 3);
});
it('Move out of bounds to the right', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 1, 4);
assert.equal(array[0], 1);
assert.equal(array[1], 3);
assert.equal(array[2], 2);
});
});
Run Code Online (Sandbox Code Playgroud)
Eli*_*dou 11
这是我的单线程ES6解决方案,带有可选参数on
.
if (typeof Array.prototype.move === "undefined") {
Array.prototype.move = function(from, to, on = 1) {
this.splice(to, 0, ...this.splice(from, on))
}
}
Run Code Online (Sandbox Code Playgroud)
适应第一个提出的解决方案 digiguru
参数on
是从from
您想要移动的元素数量.
我已经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;
};
Run Code Online (Sandbox Code Playgroud)
变量名可以缩短,只使用长的,以便代码可以自我解释。
一种方法是使用切片方法创建一个包含所需顺序的新数组.
例
var arr = [ 'a', 'b', 'c', 'd', 'e'];
var arr2 = arr.slice(0,1).concat( ['d'] ).concat( arr.slice(2,4) ).concat( arr.slice(4) );
Run Code Online (Sandbox Code Playgroud)
一种方法是使用 usesplice()
从数组中删除项目,然后splice()
再次使用方法,将删除的项目插入到目标索引中。
const array = ['a', 'b', 'c', 'd', 'e']
const newArray = moveItem(array, 3, 1) // move element from index 3 to index 1
function moveItem(arr, fromIndex, toIndex){
let itemRemoved = arr.splice(fromIndex, 1) // assign the removed item as an array
arr.splice(toIndex, 0, itemRemoved[0]) // insert itemRemoved into the target index
return arr
}
console.log(newArray)
Run Code Online (Sandbox Code Playgroud)
您可以在这里找到splice() 的简短说明
2022 年,此打字稿实用程序将与单元测试一起使用。
export const arrayMove = <T>(arr: T[], fromIndex: number, toIndex: number) => {
const newArr = [...arr];
newArr.splice(toIndex, 0, newArr.splice(fromIndex, 1)[0]);
return newArr;
};
Run Code Online (Sandbox Code Playgroud)
const testArray = ['1', '2', '3', '4'];
describe('arrayMove', () => {
it('should move array item to toIndex', () => {
expect(arrayMove(testArray, 2, 0)).toEqual(['3', '1', '2', '4']);
expect(arrayMove(testArray, 3, 1)).toEqual(['1', '4', '2', '3']);
expect(arrayMove(testArray, 1, 2)).toEqual(['1', '3', '2', '4']);
expect(arrayMove(testArray, 0, 2)).toEqual(['2', '3', '1', '4']);
});
});
Run Code Online (Sandbox Code Playgroud)
该splice
方法Array
可以帮助:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice
请记住,它可能相对昂贵,因为它必须主动重新索引数组.
小智 6
您可以实现一些基本的微积分并创建一个通用函数,用于将数组元素从一个位置移动到另一个位置.
对于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;
}
Run Code Online (Sandbox Code Playgroud)
查看"gloommatter"中的"移动数组元素"以获取详细说明.
http://www.gloommatter.com/DDesign/programming/moving-any-array-elements-universal-function.html
我需要一个不可变的移动方法(一个没有改变原始数组的方法),所以我调整了@Reid接受的答案,只需使用Object.assign在进行拼接之前创建数组的副本.
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;
};
Run Code Online (Sandbox Code Playgroud)
这是一个jsfiddle显示它在行动.
小智 5
另一个使用 ES6 数组扩展运算符的纯 JS 变体,没有突变
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))
Run Code Online (Sandbox Code Playgroud)
复制自 @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;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
371050 次 |
最近记录: |