更改数组中的元素位置并在其间移动元素
Change elements positions in an array and shift elements in between
我想选择数组中的一个元素,将其移动到另一个索引,然后 "shift/rotate" "in-between" 个元素加 1。
想象一下拖放功能,如果索引 from
小于索引 to
,那么我想向左移动,否则向右移动.
输入:
let data = [ 0, 1, 2, 3, 4, 5, 6 ]
任务 1:
insertAndShift(data, 0, 3): Take element at index 0, shift indexes 1, 2, 3 to the left, and then insert index 0 at 3
预期输出:
[ 1, 2, 3, 0, 4, 5, 6 ]
任务 2:
insertAndShift(data, 3, 0) Take element at index 3, shift indexes 0, 1, 2 to the right and then insert index 3 at 0
预期输出:
[ 0, 1, 2, 3, 4, 5, 6 ]
我试过这个:
以下 Rotating an array in place,丑陋且无法运行的代码(温度始终未定义 + 结果不完整 + 可能仅适用于 RIGHT):
insertAndShift(data, from, to)
{
if(from < to)
{
// rotate in between - LEFT
}
else
{
// swap elements
let temp = data[from];
data[from] = data[to];
data[to] = temp;
// rotate in between - RIGHT
let newData = this.rotate(data.slice(to, from - 1), 1)
let result = [];
result.push(data.slice(0,1));
newData.map((element) => result.push(element))
for(let i = from+1; i < data.length; i++)
{
result.push(data[i]);
}
this.setState({data: result})
}
}
rotate(arr, k) {
var l = arr.length;
arr = this.reverseArr(arr, 0, l - 1);
arr = this.reverseArr(arr, 0, k - 1);
arr = this.reverseArr(arr, k, l - 1);
return arr;
}
reverseArr(arr, left, right) {
while (left < right) {
var temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
return arr;
}
还关注 Javascript (dynamic) insert into array, then shift all elements underneath +1,其中 returns 只有 1 项:
else
{
let result = data.splice(to, 1, data[from]);
this.setState({allTasksArray: result})
}
我怎样才能同时为左手和右手实现这一点?
您可以使用Array.prototype.splice
剪切出您想要的元素并插入到所需的索引处(移位会自动发生):
function insertAndShift(arr, from, to) {
let cutOut = arr.splice(from, 1) [0]; // cut the element at index 'from'
arr.splice(to, 0, cutOut); // insert it at index 'to'
}
let data = [ 0, 1, 2, 3, 4, 5, 6 ];
insertAndShift(data, 0, 3);
console.log("[" + data + "]");
insertAndShift(data, 3, 0);
console.log("[" + data + "]");
上面的答案很有效,但它有点手摇......如果你对一个解决方案感兴趣,说明它在做什么,我写了这个:
const insertAndShift = (arr: number[], to: number, from: number) => {
let newArray: number[] = [];
const fromItem = arr[from];
if (from > to) {
const startToTo = (to > 0) ? arr.slice(0, to) : [];
const toToFrom = arr.slice(to, from);
const fromToEnd = arr.slice(from + 1, arr.length);
newArray = newArray.concat(startToTo, [fromItem], toToFrom, fromToEnd);
}
if (to > from) {
const startToFrom = (from > 0) ? arr.slice(0, from) : [];
const fromToTo = arr.slice(from + 1, to + 1);
const toToEnd = arr.slice(to + 1, arr.length);
newArray = newArray.concat(startToFrom, fromToTo, fromItem, toToEnd);
}
return newArray;
};
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(insertAndShift(array, 9, 0));
console.log(insertAndShift(array, 5, 1));
看看这个方法:Array.prototype.copyWithin()。
有一种更有效的就地方法:
function insertAndShift(data, src, dest) {
if (src === dest)
return;
let tmp = data[src];
if (src < dest) {
data.copyWithin(src, src + 1, dest + 1);
} else /* if (src > dest) */ {
data.copyWithin(dest + 1, dest, src);
}
data[dest] = tmp;
}
let data = [0, 1, 2, 3, 4, 5, 6];
insertAndShift(data, 0, 3);
console.log("[" + data + "]");
insertAndShift(data, 3, 0);
console.log("[" + data + "]");
下图:
Case 1 (src < dest):
[..Sabcd..]
//// // data.copyWithin(src, src+1, dest+1);
[..abcdd..]
[..abcdS..] // data[dest] = tmp;
Case 2 (src > dest):
[..abcdS..]
\\ // data.copyWithin(dest+1, dest, src);
[..aabcd..]
[..Sabcd..] // data[dest] = tmp;