【问题标题】:How to convert a bool array into a byte array如何将布尔数组转换为字节数组
【发布时间】:2022-06-12 07:36:17
【问题描述】:

如何将布尔数组转换为字节数组?

我希望结果向量的长度是输入向量的 1/8。

这样

let a = [false; 160];
let b: [u8; 20] = ???

我想我可以做一个 for 循环并做一些算术,但我想知道是否有更简单的方法。

【问题讨论】:

标签: rust


【解决方案1】:

作为基于 crate 的解决方案的替代方案,“手动”版本实施起来并不难,并且避免了分配:

    let mut b = [0u8;20];
    for (idx, bit) in a.into_iter().enumerate() {
        let byte = idx / 8;
        let shift = 7 - idx % 8;
        b[byte] |= (bit as u8) << shift;
    }

这个泛型的问题是当前的 const 泛型不支持对常量进行算术运算。

在每晚使用generic_const_expr 时,这个东西可以在任意输入大小上工作(这个不完整的实现会在不完整的尾随字节上出现恐慌):

#![feature(generic_const_exprs)]

fn to_bits<const N: usize>(bools: [bool;N]) -> [u8;N/8] {
    let mut out = [0;N/8];
    for (idx, bit) in bools.into_iter().enumerate() {
        let byte = idx / 8;
        let shift = 7 - idx % 8;
        out[byte] |= (bit as u8) << shift;
    }
    out
}

fn main() {
    let mut a = [false; 160];
    a[42] = true;
    let b = to_bits(a);
    println!("{:?}", b);
}

虽然我认为 bitvec 也有一个 BitArray 类型,它可能也允许在没有分配的情况下执行此操作。

【讨论】:

  • 您采用了与我相反的位字节序。在您的第一段代码中,let shift = 7 - idx % 8; 可以替换为 let shift = idx % 8; 以翻转位字节序。
  • 如果N % 8 != 0 可能会中断,例如[bool;15] 变成 [u8; 1] 这绝对是错误的。也许[0; (N+7)/8]
  • @Finomnis 它不会变成任何东西,它目前处于恐慌状态,如答案中所述。如果您认为这很重要,请随时修复它(并删除注释)。
  • 并非如此。人们可以看到这个概念。
【解决方案2】:

这有效,不需要新的依赖项。

    let mut b = [0u8;20];
    for i in 0..160 {
        b[i / 8] |= u8::from(a[i]) << (i % 8);
    }

【讨论】:

    【解决方案3】:

    使用bitvec crate,这样的事情应该会接近:

    use bitvec::vec::BitVec;
    
    let a = [false; 160];
    let b = [0; 20]
    b[..].copy_from_slice (a.iter().collect::<BitVec>().as_raw_slice());
    

    【讨论】:

      【解决方案4】:

      我认为仅使用内置的 std 库无法做到这一点。

      不过,有了出色的 bit-vec 板条箱:

      use bit_vec::BitVec;
      
      fn main() {
          let mut a = [false; 160];
          a[42] = true;
      
          let bitvec: BitVec = a.into_iter().collect();
      
          let b: [u8; 20] = bitvec.to_bytes().try_into().unwrap();
      
          println!("{:?}", b);
      }
      
      [0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      

      您可以将它放在通用函数中,但这需要夜间和不稳定的功能:

      #![feature(generic_const_exprs)]
      
      use bit_vec::BitVec;
      
      fn convert_vector<const N: usize>(bits: [bool; N]) -> [u8; N / 8] {
          let bitvec: BitVec = bits.into_iter().collect();
          bitvec.to_bytes().try_into().unwrap()
      }
      
      fn main() {
          let mut a = [false; 160];
          a[42] = true;
      
          println!("{:?}", convert_vector(a));
      }
      

      【讨论】:

        猜你喜欢
        • 2014-08-10
        • 1970-01-01
        • 2013-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多