我很难弄清楚如何移动数组中的一个元素。例如,给定以下条件:
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']
这看起来应该很简单,但我无法理解它。
当前回答
在你的例子中,因为是一个字符串数组,我们可以使用一个ranking对象来重新排列字符串数组:
let rank = { 'a': 0, 'b': 1, 'c': 2, 'd': 0.5, 'e': 4 };
arr.sort( (i, j) => rank[i] - rank[j] );
我们可以使用这种方法来编写一个move函数,它工作在字符串数组上:
函数stringArrayMove(from, to) { 令rank = arr。Reduce ((p, c, i) => (p [c] = i, p), ({})); / /等级= {a: 0,“b”:1、“c”:2,' d ': 3,“e”:4} Rank [arr[from]] = - 0.5; / /等级= {a: 0,“b”:1、“c”:2,' d ': 1.5,“e”:4} 加勒比海盗。排序((i, j) => rank[i] - rank[j]); // arr = ['a', 'd', 'b', 'c', 'e']; } Let arr = ['a', 'b', 'c', 'd', 'e']; stringArrayMove(arr, 3,1); console.log(JSON.stringify(arr));
然而,如果我们想要排序的是一个对象数组,我们可以将排序作为每个对象的新属性,即。
let arr = [ { value: 'a', rank: 0 },
{ value: 'b', rank: 1 },
{ value: 'c', rank: 2 },
{ value: 'd', rank: 0.5 },
{ value: 'e', rank: 4 } ];
arr.sort( (i, j) => i['rank'] - j['rank'] );
我们可以使用Symbol来隐藏这个属性的可见性,即它不会在JSON.stringify中显示。我们可以在objectArrayMove函数中泛化它:
function objectArrayMove(arr, from, to) { let rank = Symbol("rank"); arr.forEach( (item, i) => item[rank] = i ); arr[from][rank] = to - 0.5; arr.sort( (i, j) => i[rank] - j[rank]); } let arr = [ { value: 'a' }, { value: 'b' }, { value: 'c' }, { value: 'd' }, { value: 'e' } ]; console.log( 'array before move: ', JSON.stringify( arr ) ); // array before move: [{"value":"a"},{"value":"b"},{"value":"c"},{"value":"d"},{"value":"e"}] objectArrayMove(arr, 3, 1); console.log( 'array after move: ', JSON.stringify( arr ) ); // array after move: [{"value":"a"},{"value":"d"},{"value":"b"},{"value":"c"},{"value":"e"}]
其他回答
这是一个非常简单的使用拼接的方法
Array.prototype.moveToStart = function(index) {
this.splice(0, 0, this.splice(index, 1)[0]);
return this;
};
我已经实现了一个不可变的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;
};
变量名可以缩短,只使用长变量名,这样代码就可以解释自己。
我以为这是个交换问题,但其实不是。下面是我的一句话解决方案:
const move = (arr, from, to) => arr.map((item, i) => i === to ? arr[from] : (i >= Math.min(from, to) && i <= Math.max(from, to) ? arr[i + Math.sign(to - from)] : item));
下面是一个小测试:
let test = ['a', 'b', 'c', 'd', 'e'];
console.log(move(test, 0, 2)); // [ 'b', 'c', 'a', 'd', 'e' ]
console.log(move(test, 1, 3)); // [ 'a', 'c', 'd', 'b', 'e' ]
console.log(move(test, 2, 4)); // [ 'a', 'b', 'd', 'e', 'c' ]
console.log(move(test, 2, 0)); // [ 'c', 'a', 'b', 'd', 'e' ]
console.log(move(test, 3, 1)); // [ 'a', 'd', 'b', 'c', 'e' ]
console.log(move(test, 4, 2)); // [ 'a', 'b', 'e', 'c', 'd' ]
console.log(move(test, 4, 0)); // [ 'e', 'a', 'b', 'c', 'd' ]
作为里德精彩回答的补充(因为我无法评论); 你可以使用模数来让负标和过大的下标“滚动”:
函数array_move(arr, old_index, new_index) { New_index =((New_index % arr.length) + arr.length) % arr.length; 加勒比海盗。拼接(new_index, 0, arr.)拼接(old_index, 1) [0]); 返回arr;//用于测试 } //返回[2,1,3] Console.log (array_move([1,2,3], 0,1));
我使用不可变性助手库解决了我的问题。
import update from 'immutability-helper';
const move = (arr: any[], from: number, to: number) => update(arr, {
$splice: [
[from, 1],
[to, 0, arr[from] as string],
],
});
const testArray = ['a', 'b', 'c', 'd', 'e'];
console.log(move(testArray, 1, 3)); // [ 'c', 'b', 'c', 'd', 'e' ]
console.log(move(testArray, 4, 0)); // [ 'e', 'b', 'c', 'd', 'a' ]