为具有多个参数的矩阵实现索引运算符

use*_*784 5 struct rust

我正在尝试创建一个Matrix结构,并且我想覆盖Index运算符以让我拥有矩阵样式的索引。

例如:

let m = Matrix { ... DATA ... }
let entry = m[0,0]
Run Code Online (Sandbox Code Playgroud)

我的结构是这样的:

struct Matrix {
    cols: usize,
    rows: usize,
    data: Vec<f32>
}
Run Code Online (Sandbox Code Playgroud)

我一直在研究Index trait,但我不知道如何使这项工作发挥作用?另外,我希望能够在每个维度等中获取范围。

She*_*ter 9

简而言之,你不能这样做。的Index性状的定义为:

pub trait Index<Idx: ?Sized> {
    type Output: ?Sized;
    fn index(&self, index: Idx) -> &Self::Output;
}
Run Code Online (Sandbox Code Playgroud)

也就是说,它需要一个单一类型的参数Idx。您可以做的最接近的是使用元组,它是一种包含多个值的单一类型:

impl std::ops::Index<(usize, usize)> for Matrix {
    type Output = f32;

    fn index(&self, idx: (usize, usize)) -> &f32 {
        // or as appropriate for row- or column-major data       
        &self.data[idx.0 * self.cols + idx.1]
    }
}
Run Code Online (Sandbox Code Playgroud)

它会被称为

matrix[(0, 1)]
Run Code Online (Sandbox Code Playgroud)

bluss指出的是,多阵列板条箱使用两个元件阵列而不是一个元组。这可能更容易输入,因为您只需按两次方括号即可:

impl std::ops::Index<[usize; 2]> for Matrix {
    type Output = f32;

    fn index(&self, idx: [usize; 2]) -> &f32 {
        // or as appropriate for row- or column-major data       
        &self.data[idx[0] * self.cols + idx[1]]
    }
}
Run Code Online (Sandbox Code Playgroud)

它被称为 like matrix[[0, 1]]。重要的是,仍然只有一个值作为参数提供给index

根据需要进行重复执行RangeRangeToRangeFrom,和RangeFull。这些都是单一类型,因此您可以将其称为 like matrix[5..],无论这可能意味着什么。

  • 使用数组而不是元组是我从 [multiarray](https://github.com/sellibitze/multiarray) 看到的一个很好的技巧。`matrix[[0, 1]]` 看起来不错并且更容易输入。 (2认同)

Luk*_*odt 8

另一种可能性是使用二维数组样式索引,如m[0][1]. 这绝对是可能的——在你的情况下甚至很容易。您的Index实现只需要返回可再次索引的内容。代码:

use std::ops::Index;

struct Matrix {
    cols: usize,
    rows: usize,
    data: Vec<f32>
}

impl Index<usize> for Matrix {
    type Output = [f32];
    fn index(&self, index: usize) -> &Self::Output {
        &self.data[index * self.cols .. (index+1) * self.cols]
    }
}

fn main() {
    let m = Matrix {
        cols: 2,
        rows: 2,
        data: vec![1., 2., 3., 4.],
    };

    println!("{} {}", m[0][0], m[0][1]);
    println!("{} {}", m[1][0], m[1][1]);
}
Run Code Online (Sandbox Code Playgroud)

这种风格在 Java 和 C 等语言中更为常见。