Rust 相对数组索引

Mat*_*ete 0 unsigned-integer rust integer-arithmetic

我是一名相当高级的程序员(有 Java、Python、C#、C、C++ 经验),现在第一次尝试学习 Rust。Rust 与我之前尝试过的任何语言都非常不同,所以我很挣扎。为了了解这门语言,我正在实现一个小游戏。

在我的代码中的某个时刻,我想访问“板”中的一个元素和周围的元素。如果我的元素位于板的边缘(索引 0 或索引最大值),我需要一个剪裁值(例如索引 0 - 1 == 0) 如果我简化这个用例,我会尝试从数组和相对索引。下面是一个非常小的例子:

fn get_elements(array: &Vec<char>, i: usize, dx: i8) -> (char, char) {
    let center = array[i];
    let other = array[i+dx];
    (center, other)
}

fn main() {
    let data = vec!['a', 'b', 'c', 'd', 'e'];
    let (c, o) = get_elements(&data, 2, -1);
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,这无法编译,因为no implementation for `usize + i8` . 我理解这是因为对于无符号数来说,减去零以下的行为是未定义的。然而,我不清楚如何在 Rust 中实现所需的行为。

Ry-*_*Ry- 5

有\xe2\x80\x99s usize::saturating_add_signed

\n
fn get_elements(array: &[char], i: usize, dx: isize) -> (char, char) {\n    let center = array[i];\n    let other = array[i.saturating_add_signed(dx).min(array.len() - 1)];\n    (center, other)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,为了方便起见,我将其更改dxisize(如果您想保留它,isize::from(dx)=将起作用),并且因为您不需要\xe2\x80\x99t 的 ness 。dx.into()i8array&[char]Vec

\n

或者,您可能会发现如下所示的选项,其中索引经过的选项isize更具可读性。唯一的行为差异是usizes 不适合isize,在大多数情况下考虑超出范围是不合理的。

\n
let len: isize = array.len().try_into().unwrap();\nlet center = array[i];\nlet other = array[(i as isize + dx).clamp(0, len - 1) as usize];\n(center, other)\n
Run Code Online (Sandbox Code Playgroud)\n
\n

我理解这是因为对于无符号数来说,减去零以下的行为是未定义的。

\n
\n

减去零以下实际上是明确定义的,可以在调试版本中出现恐慌并在发布版本中进行包装,但它\xe2\x80\x99s是明确的,是的。

\n