当前位置: 首页 > 知识库问答 >
问题:

二维数组应该使用什么类型?

姬英武
2023-03-14

这里的a类型有什么问题?

fn foo(a: &[&[f64]], x: &[f64]) {
    for i in 0..3 {
        for j in 0..4 {
            println!("{}", a[i][j]);
        }
    }
}

fn main() {
    let A: [[f64; 4]; 3] = [
        [1.1, -0.2, 0.1, 1.6],
        [0.1, -1.2, -0.2, 2.3],
        [0.2, -0.1, 1.1, 1.5],
    ];
    let mut X: [f64; 3] = [0.0; 3];

    foo(&A, &X);
}

我得到编译失败:

error[E0308]: mismatched types
  --> src/main.rs:17:9
   |
17 |     foo(&A, &X);
   |         ^^ expected slice, found array of 3 elements
   |
   = note: expected type `&[&[f64]]`
              found type `&[[f64; 4]; 3]`

共有2个答案

胡墨竹
2023-03-14

作为Shepmaster对机制的良好解释的替代,实际上还有另一种方法可以让你的函数接受数组和切片的任何混合(甚至Vec):它涉及到使用具有AsRef特性的泛型。

这个想法是这样写你的函数:

use std::convert::AsRef;

fn foo<S, T, U>(a: S, x: U)
where
    T: AsRef<[f64]>,
    S: AsRef<[T]>,
    U: AsRef<[f64]>,
{
    let slice_a = a.as_ref();
    for i in 0..slice_a.len() {
        let slice_aa = slice_a[i].as_ref();
        for j in 0..slice_aa.len() {
            println!("{}", slice_aa[j]);
        }
    }
}

这是一个相当大的函数,但实际上相当简单:S必须强制一个

这样,S可以是一个切片数组,一个数组数组,一个Vec数组,也可以是一个切片数组,一个向量数组。。。只要类型实现了AsRef特性,任何组合都是可能的。

但是要小心:AsRef特性只在大小不超过32的数组中实现。

方梓
2023-03-14

数组与切片的类型不同。值得注意的是,数组的大小是固定的,在编译时就知道了。切片具有固定大小,但仅在运行时已知。

我在这里看到了两个直接的选择(见莱文斯对另一个的回答)。首先是将函数更改为只接受对数组(或整个数组,如果您可以复制它或不介意放弃所有权)的引用:

fn foo(a: &[[f64; 4]; 3], x: &[f64; 3]) {
    for i in 0..3 {
        for j in 0..4 {
            println!("{}", a[i][j]);
        }
    }
}

fn main() {
    let a = [
        [1.1, -0.2, 0.1, 1.6],
        [0.1, -1.2, -0.2, 2.3],
        [0.2, -0.1, 1.1, 1.5],
    ];

    let x = [0.0; 3];

    foo(&a, &x);
}

另一个简单的更改是将声明转换为引用:

fn foo(a: &[&[f64]], x: &[f64]) {
    for i in 0..3 {
        for j in 0..4 {
            println!("{}", a[i][j]);
        }
    }
}

fn main() {
    let a = [
        &[1.1, -0.2, 0.1, 1.6][..],
        &[0.1, -1.2, -0.2, 2.3][..],
        &[0.2, -0.1, 1.1, 1.5][..],
    ];

    let x = [0.0; 3];

    foo(&a, &x);
}

请注意,在第二个例子中,我们可以使用对一个数组的引用的隐式强制,当我们只是传入

还有一个警告——你真的应该在你的范围内使用切片的长度方法,否则你很容易感到恐慌!如果你走到尽头。

fn foo(a: &[&[f64]], x: &[f64]) {
    for i in 0..a.len() {
        let z = &a[i];
        for j in 0..z.len() {
            println!("{}", z[j]);
        }
    }
}

我为满足Rust风格所做的其他风格变化:

  1. 变量是snake_case
  2. 后的空格:
  3. 后的空格;
  4. 周围的空间=< /code>
  5. 后的空格,

 类似资料:
  • 问题内容: 在工作中进行大量重构的中间,我希望引入stdClass *作为从函数返回数据的一种方式,并且我试图找到非主观论据来支持我的决定。 是否有任何情况下最好使用一种而不是另一种? 使用stdClass而不是数组有什么好处? 有人会说,函数必须尽可能少且特定,才能返回一个值。 我决定使用stdClass是暂时的,因为从长远来看,我希望为每个进程找到正确的Value Objects。 问题答案:

  • 问题内容: 我知道他们两个都禁用了Nagle的算法。 我什么时候应该/不应该使用它们中的每一个? 问题答案: 首先,不是所有人都禁用Nagle的算法。 Nagle的算法用于减少有线中更多的小型网络数据包。该算法是:如果数据小于限制(通常是MSS),请等待直到收到先前发送的数据包的ACK,同时累积用户的数据。然后发送累积的数据。 这将对telnet等应用程序有所帮​​助。但是,在发送流数据时,等待A

  • 问题内容: 在该类中,有两个字符串,和。 有什么不同?我什么时候应该使用另一个? 问题答案: 如果你的意思是和则: 用于在文件路径列表中分隔各个文件路径。考虑在上的环境变量。您使用a分隔文件路径,因此在上将是;。 是或用于拆分到特定文件的路径。例如在上,或

  • 我正在编写一个计算和绘制抛物线的小程序。但我在程序中有一小部分需要计算valuetable。 二次函数如下:

  • 二维数组 #include <stdio.h> #include <stdlib.h> //01.二维数组: // 1.二维数组的内存存储原理: // 所有数组,无论一维数组,二维数组,多维数组,在内存当中的 // 存储实质都是采取的连续存储方式 // 2.二维数组的规律赋值方式: // 先进行行遍历,在进行列遍历,再逐个进行逐个数组元素的具体赋值操作 //