在Rust中创建向量的向量

Ian*_*ing 5 vector matrix rust

这段代码不会编译:

fn main() {
    let m1 = vec![1, 2, 3];
    let m2 = vec![&m1, &m1, &m1];
    let m3 = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];

    for i in &m2 {
        for j in i {
            println!("{}", j);
        }
    }

    for i in &m3 {
        for j in i {
            println!("{}", j);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
fn main() {
    let m1 = vec![1, 2, 3];
    let m2 = vec![&m1, &m1, &m1];
    let m3 = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];

    for i in &m2 {
        for j in i {
            println!("{}", j);
        }
    }

    for i in &m3 {
        for j in i {
            println!("{}", j);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. m2m3那有什么不同m3不会造成问题,但m2防止编译?

  2. 有没有更简单的方法来创建...的向量到任何所需的深度?我的工作方式(m3)似乎很笨拙。

Luk*_*odt 5

如何m2不同于m3...

逐步检查类型。m1是类型Vec<isize>(也可以是其他任何整数类型,但我认为isize现在是这样)。为什么?因为vec![]宏中的元素是type isize。现在您正在创建m2

let m2 = vec![&m1, &m1, &m1];
Run Code Online (Sandbox Code Playgroud)

此宏中元素的类型是什么?好吧,我们已经说过m1有类型Vec<isize>&m1有类型也有&Vec<isize>。因此,的最终类型m2Vec<&Vec<isize>>(一个完全包含对其他向量的引用的向量)。

但是,m3类型为Vec<Vec<isize>>,因为(外部)vec![]宏中的元素为类型Vec<isize>(无引用!)。

提示要轻松检查任何变量的类型(例如foo),请输入:

let _: () = foo;
Run Code Online (Sandbox Code Playgroud)

这将导致编译器错误,告诉您的类型foo

...这样不会m3导致任何问题,但是会m2阻止编译?

现在我们知道了m2和的类型m3,让我们看一下循环。for循环通过接受实现的东西来工作IntoIterator。您正在传递&m2,其类型为&Vec<&Vec<isize>>(请注意两个引用)。我们可以看到IntoIterator确实实现了对矢量的引用:

impl<T> IntoIterator for &Vec<T> {
    type Item = &T
    // ...
}
Run Code Online (Sandbox Code Playgroud)

这意味着您将获得一个迭代器,该迭代器吐出对内部类型Ttype Item = &T)的引用。我们的内部类型m2&Vec<isize>,因此我们将获得类型的项目&&Vec<isize>(两个引用!)。您的变量i具有此确切类型。

然后,您要使用此内部循环再次进行迭代:

for j in i { ... }
Run Code Online (Sandbox Code Playgroud)

但是i具有这种双重引用类型,并且没有IntoIterator针对该类型的实现。要对其进行迭代,您必须像这样取消引用它:

for j in *i { ... }
Run Code Online (Sandbox Code Playgroud)

甚至更好:通过在外部循环中使用模式匹配将其剥离,使其i成为类型&Vec<isize>(一个引用!):

for &i in &m2 { ... }
Run Code Online (Sandbox Code Playgroud)

您的m3循环执行相同的操作,但是由于m3它是另一种类型(较少引用),因此可以正常工作(希望您能明白为什么)。


有没有更简单的方法来创建...的向量vector到任何所需的深度

即使m2有效,它也不会拥有与相同的值m3。要创建m2类型Vec<Vec<isize>>(如m3),您应该clone m1不要引用它。

let m2 = vec![m1.clone(), m1.clone(), m1.clone()];
Run Code Online (Sandbox Code Playgroud)

通过使用vec![_; _]宏的形式,我们可以做得更好:

let m2 = vec![m1; 3];   // three times the value of `m1`
Run Code Online (Sandbox Code Playgroud)

最后一点,您应该考虑使用nested Vec。嵌套会产生开销,因为这些值分布在整个内存中,而不是放在一个位置。