如何更改向量元素的索引?

Gir*_*rpa -2 vector rust

在 JavaScript 中我会这样做:

function 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;
    while ((k--) + 1) {
      arr.push(undefined);
    }
  }
  arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
  return arr;
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能在 Rust 中完成同样的事情?

我不想使用insertandremove因为我的向量是 astd::vec::Vec<std::string::String>并且我想将它们从字面上移动到向量中的不同位置,而不是删除它们然后插入副本。

我不想交换 2 个元素。我想将一个元素的索引更改为任意其他索引,就像一个人切到队列中的任意其他位置一样。

tre*_*tcl 8

当您执行insert+ remove(或 JavaScript 中的 double splice)时,您将两个索引中较大的一个和数组末尾之间的所有项目移动两次:首先将它们向后移动一个位置remove,然后将它们向前移动一个位置为了insert。但这是不必要的。相反,您可以简单地截取一部分Vec并旋转它:

fn move_me(arr: &mut [String], old_index: usize, new_index: usize) {
    if old_index < new_index {
        arr[old_index..=new_index].rotate_left(1);
    } else {
        arr[new_index..=old_index].rotate_right(1);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,此更改允许move_metake&mut [String]代替&mut Vec<String>,这使得此代码更通用且更高效。最好接受&[T]而不是&Vec<T>,在这种情况下,相同的逻辑适用于&mut Vec<T>因为move_me不需要增大或缩小向量。

另外,正如在另一个答案中一样,我省略了使负索引从切片后面计数的部分,以及当索引太大时增加向量的部分,因为这些约定在惯用的 Rust 中都不常见。