在Rust中创建向量的向量 [英] Creating a Vector of Vectors in Rust

查看:318
本文介绍了在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);
        }
    }
}

error[E0277]: the trait bound `&&std::vec::Vec<{integer}>: std::iter::Iterator` is not satisfied
 --> src/main.rs:8:18
  |
8 |         for j in i {
  |                  ^ `&&std::vec::Vec<{integer}>` is not an iterator; maybe try calling `.iter()` or a similar method
  |
  = help: the trait `std::iter::Iterator` is not implemented for `&&std::vec::Vec<{integer}>`
  = note: required by `std::iter::IntoIterator::into_iter`

  1. m2m3有何不同,以致m3不会引起问题,但m2会阻止编译?

  1. How is m2 different than m3 such that m3 causes no issues, but m2 prevents compilation?

是否有一种更简单的方法来创建向量...的向量到所需的深度?我的工作方式(m3)似乎很笨拙.

Is there an easier way to create a vector of vector of... to any desired depth? The way I have it working (m3) seems so clunky.

推荐答案

m2m3有何不同...

How is m2 different than m3 ...

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

Check the types step by step. m1 is of type Vec<isize> (it could be any other integer type as well, but I assume it's isize for now). Why? Because the elements in the vec![] macro are of type isize. Now you are creating m2:

let m2 = vec![&m1, &m1, &m1];

此宏中元素的类型是什么?好了,我们已经说过m1具有类型Vec<isize>,所以&m1具有类型&Vec<isize>.因此,结果m2的类型为Vec<&Vec<isize>>(一个充满对其他向量的引用的向量).

What is the type of the elements in this macro? Well we already said m1 has the type Vec<isize>, so &m1 has the type &Vec<isize>. So the resulting type of m2 is Vec<&Vec<isize>> (a vector full of references to other vectors).

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

However, m3 is of type Vec<Vec<isize>>, since the elements in the (outer) vec![] macro are of type Vec<isize> (no reference!).

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

Hint: to easily check the type of any variable (such as foo), type:

let _: () = foo;

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

This will result in a compiler error that tells you the type of foo.

...使得m3不会出现问题,但是m2会阻止编译?

... such that m3 causes no issues, but m2 prevents compilation?

现在我们知道了m2m3的类型,让我们看一下循环. for通过接受实现 IntoIterator .您正在传递类型为&Vec<&Vec<isize>>&m2(请注意两个引用). 我们可以看到IntoIterator确实针对对向量的引用:

Now that we know the types of m2 and m3, lets look at the loops. for loops work by accepting something that implements IntoIterator. You are passing &m2, which is of type &Vec<&Vec<isize>> (note the two references). We can see, that IntoIterator is indeed implemented for a reference to a vector:

impl<T> IntoIterator for &Vec<T> {
    type Item = &T
    // ...
}

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

This means that you get an iterator that spits out references to the inner type T (type Item = &T). Our inner type of m2 is &Vec<isize>, so we will get items of type &&Vec<isize> (two references!). Your variable i has this exact type.

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

Then you want to iterate again with this inner loop:

for j in i { ... }

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

But i has this double-reference type and there isn't an implementation of IntoIterator for that type. To iterate it, you have to either dereference it like:

for j in *i { ... }

甚至更好:将i设为&Vec<isize>类型(一个参考!),方法是在外循环中使用模式匹配将其剥离:

Or even better: make i be of the type &Vec<isize> (one reference!) by stripping it away with pattern matching in the outer loop:

for &i in &m2 { ... }

您的m3循环执行相同的操作,但是由于m3是另一种类型(较少引用),因此它可以工作(希望您能看到原因).

Your m3 loop does the same, but since m3 is of another type (with one reference less), it works (I hope you can see why).

有没有一种简便的方法可以创建一个向量...到任意所需深度的向量

Is there an easier way to create a vector of vector of... to any desired depth

即使m2工作正常,它也不会具有与m3相同的值.要使m2的类型为Vec<Vec<isize>>(如m3),应使用clone m1而不是对其进行引用.

Even if m2 worked, it wouldn't hold the same values as m3. To make m2 of the type Vec<Vec<isize>> (like m3), you should clone m1 instead of taking a reference to it.

let m2 = vec![m1.clone(), m1.clone(), m1.clone()];

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

We can do even better by using the vec![_; _] form of the macro:

let m2 = vec![m1; 3];   // three times the value of `m1`

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

As a last note, you should consider not using nested Vecs. The nesting creates overhead because the values are spread over the whole memory instead of being in one place.

这篇关于在Rust中创建向量的向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆