rust - 类型转换和转换

标签 rust casting type-conversion

我是 rust 的初学者。我的脚本很简单,但是我不得不使用太多的类型转换。
脚本要点:搜索矩阵中具有相同值的邻近cel的簇(使用队列https://en.wikipedia.org/wiki/Flood_fill使用洪水填充算法)。
这是完整的代码:

fn find_clusters(playground: [[u8; SIZE]; SIZE]) -> Vec<Cluster> {
    
    let directions_cluster: [[i8; 2]; 4] = [[0, 1], [0, -1], [1, 0], [-1, 0]];
    
    let mut clusters: Vec<Cluster> = Vec::new();
    let mut queue: Vec<[usize; 2]> = Vec::new();

    let mut marked_cells: [[u8; SIZE]; SIZE] = [[0; SIZE]; SIZE];

    for i in 0..SIZE {
        for j in 0..SIZE {

            if marked_cells[i][j] == 1 { continue; }

            let code = playground[i][j];
            let mut cluster = Cluster::new();

            queue.push([i, j]);
            marked_cells[i][j] = 1;

            while !queue.is_empty() {
                
                let coords = queue.pop().unwrap();

                cluster.coords.push(coords);

                for direction in &directions_cluster {

                    let check_i = coords[0] as i8 + direction[0];
                    if check_i < 0 || check_i as usize >= SIZE {continue;}

                    let check_j = coords[1] as i8 + direction[1];
                    if check_j < 0 || check_j as usize >= SIZE {continue;}

                    let ni = check_i as usize;
                    let nj = check_j as usize;
                    
                    if playground[ni][nj] == code && marked_cells[ni][nj] == 0 {
                        queue.push([ni, nj]);
                        marked_cells[ni][nj] = 1;
                    }
                }
            }
            
            if cluster.coords.len() >= 5 {
                cluster.code = code;
                clusters.push(cluster);
            }
        };
    };

    return clusters;
}
但是我不喜欢这部分:
for direction in &directions_cluster {

    let check_i = coords[0] as i8 + direction[0];
    if check_i < 0 || check_i as usize >= SIZE {continue;}

    let check_j = coords[1] as i8 + direction[1];
    if check_j < 0 || check_j as usize >= SIZE {continue;}

    let ni = check_i as usize;
    let nj = check_j as usize;
    
    if playground[ni][nj] == code && marked_cells[ni][nj] == 0 {
        queue.push([ni, nj]);
        marked_cells[ni][nj] = 1;
    }
}
我什至不得不定义其他变量(check_i,check_j),以免以后每次都对ni/nj使用强制转换。
在哪种情况下,类型转换的最佳方法是什么?

最佳答案

您可以使用标准库中的 TryInto 特性来抽象溢出检查。这就是我要实现的方式:

use std::convert::TryInto;

type Pos = [usize; 2];

fn add_to_coords(coords: Pos, offset: [i8; 2]) -> Option<Pos> {
  let ni: usize = (coords[0] as i8 + direction[0]).try_into().ok()?;
  let nj: usize = (coords[1] as i8 + direction[1]).try_into().ok()?;
  [ni, nj]
}

// ...

  for [ni, nj] in directions.flat_map(|dir| add_to_coords(coords, dir)) {
    // ...
  }

// ...  
调用flat_map会过滤掉所有None的返回值,以防您想知道continue的去向。

关于rust - 类型转换和转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64276590/

相关文章:

iterator - Rust 中的 Euler 项目 #2

postgresql - 如何将 tokio_postgres 与 Warp 结合使用?

struct - 如何类型转换和继承 Rust 结构?

c - 强制转换函数实际上如何在 C 中工作?

c++ - 什么时候必须/应该使用 dynamic_cast 而不是 static_cast?

c++ - 快速 strlen 函数与别名规则

rust - "borrowed value does not live long enough"trie插入错误

c++ - 如何转换指针以调用派生类函数/方法? C++

Lua 参数问题

c++ - 对 "same"类型转换的不同结果感到困惑, float 到 int