首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将循环展开为宏,使数组不可变

将循环展开为宏,使数组不可变
EN

Code Review用户
提问于 2020-04-14 02:23:45
回答 1查看 85关注 0票数 0

我昨天写了这些生锈的字。它将27位从32位整数转换为3x9字节数组,但我的直觉是,这应该在没有可变变量ans的情况下完成。

代码语言:javascript
复制
pub fn u32_to_preformated_vector(image:u32) ->[[u8;9];3] {
  let mut ans:[[u8; 9]; 3]= [[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
  let image = !image;
  for i in 0..27 {
     ans[i/9][i%9] = 1 & (image >> i) as u8;
  }
  ans
}

什么才是这里最干净的代码?宏还是迭代器魔法?

EN

回答 1

Code Review用户

发布于 2020-04-16 10:54:57

也请参见这里的代码:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=574d96b16d82c5816ebc35c5d88acda2

函数u32_to_preformated_vector的名称让我假设我得到的是我实际得到的东西。所以我认为这个名字可以改进:

  • 函数实际上不返回向量,而是返回数组;
  • 该函数对输入位进行反转。在名字里是完全看不见的。
  • 您甚至可以指示您处理转换的位顺序,因为并不是每个人都希望首先得到最不重要的位/最不重要的非get。

在保持可变数组的情况下,我使用了以下代码:

代码语言:javascript
复制
pub fn u32_to_preformatted_array(image: u32) -> [[u8; 9]; 3] {
    let mut result = [[0u8; 9]; 3];
    let inverted = !image;
    for n in 0..3 {
        let nonet = inverted >> n * 9;
        for m in 0..9 {
            result[n][m] = 1 & (nonet >> m) as u8;
        }
    }
    result
}

我想如果我将倒置的image绑定到一个新的名称(inverted)上会有帮助。这样,在for循环中,读者可以看到它与作为参数传递给函数的值是不同的。

我还将单个for循环转换为两个嵌套的for循环。虽然嵌套这些循环通常可能会导致性能问题,但在这里它并没有坏处,因为内部代码中的迭代次数保持不变(27)。这样,我认为索引处理比做一个除法和一个余数来计算它们更清楚。它也可能使比特顺序变得更加明显。

数组的初始值可以以更紧凑的方式初始化,因为数组中的所有值都是相同的(本例中为0u8)。

我不认为在函数中有一个可变数组是一件大事。虽然我在很大程度上追求的是不变性,但在这里,变异的可能性是非常有限的。由于这是一个价值得到建造的地方,所以在不同的地方使用它是没有危险的。从返回值的点开始,函数的声明将使其不可变。

我还试图通过使用迭代器来摆脱这个单一的mut。只要将函数的返回类型从数组更改为向量,就很容易:

代码语言:javascript
复制
pub fn u32_to_preformatted_vec(image: u32) -> Vec> {
    let inverted = !image;
    (0..3)
        .map(|i| (inverted >> 9 * i) & 0b111_111_111) // `&` not strictly needed
        .map(|nonet| (0..9).map(|i| 1 & (nonet >> i) as u8).collect())
        .collect()
}

一般来说,我认为在map/reduce样式中工作比在数组上工作要好得多。您也可以将Vec转换为片,但是对数组的转换更困难,而且常常使用像.clone_from_slice()这样的函数来完成,因为这需要一个以前分配的数组,这个数组又是可变的。我还尝试为Vec获取一个切片,然后使用TryFrom特性将其转换为一个数组。当我让它在一维数组中工作时,我没有让它在多维数组[[u8; 9]; 3]中工作。

在设计解决方案时,也很少需要从Vec到数组。Vec只是数组周围的一点代码(这就是为什么可以很容易地从它得到一个片段)。因此,在使用数组时,您不会真正保存任何东西。

考虑到整个问题,我想知道这种转换的原因是什么。您正在释放一个4字节的值,最多可以使用27字节的内存。这样可以增加程序的内存使用量,我不知道你从中得到了什么。我不认为它实际上会提高性能,因为在访问数据时,您会失去局部性。计算机中的缓存将不能像使用原始的4字节值那样工作。

如果您试图从转换中获得的目标是提高可读性,我认为您可能会尝试定义帮助函数来获取(或设置)各个位。计算实际上非常容易,在CPU寄存器中执行,编译器可以内联。那应该相当快,…比将数据转换到这个二维数组更快,这需要大量访问计算机内存,因为它不能在寄存器中完成。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/240480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档