【问题标题】:How to convert an iterator of [u8; 4] into an iterator of u8?如何转换 [u8; 的迭代器; 4]进入u8的迭代器?
【发布时间】:2021-05-14 13:47:53
【问题描述】:

我有 u8 数据需要扩展为更多字节,[u8; 4] 通过函数并将其作为迭代器整体传递给使用它的第二个函数。

以下编译但不起作用,因为它多次调用消费函数:

fn expand(b: u8) -> [u8; 4] {
    const T: [u8; 4] = [0x12, 0x34, 0x56, 0x78];
    [
        T[((b >> 6) & 0b11) as usize],
        T[((b >> 4) & 0b11) as usize],
        T[((b >> 2) & 0b11) as usize],
        T[((b >> 0) & 0b11) as usize],
    ]
}

fn process2(data: impl Iterator<Item = [u8; 4]>) {
    for x in data {
        process(x.iter().cloned());
    }
}

fn process(data: impl Iterator<Item = u8>) { 
    for x in data {
        println!("{:02x}", x);
    }
}

fn main() {
    let xs = [1, 2, 3, 4];
    process2(xs.iter().map(|x| expand(*x)));
}

Playground

flat_map 似乎是答案,但我遇到了终身问题:

    process(xs.iter().map(|x| expand(*x)).flat_map(|x| x.iter().cloned()));

给我:

error[E0515]: cannot return value referencing function parameter `x`
  --> src/main.rs:27:56
   |
27 |     process(xs.iter().map(|x| expand(*x)).flat_map(|x| x.iter().cloned()));
   |                                                        -^^^^^^^^^^^^^^^^
   |                                                        |
   |                                                        returns a value referencing data owned by the current function
   |                                                        `x` is borrowed here

如何将Iterator&lt;Item=[u8; 4]&gt; 转换为Iterator&lt;Item=u8&gt;

【问题讨论】:

    标签: arrays rust iterator


    【解决方案1】:

    我建议创建一个自定义迭代器:

    struct NameMe {
        i: u8,
        v: u8,
    }
    
    impl NameMe {
        fn new(v: u8) -> Self {
            Self { i: 8, v }
        }
    }
    
    impl Iterator for NameMe {
        type Item = u8;
    
        fn next(&mut self) -> Option<Self::Item> {
            const T: [u8; 4] = [0x12, 0x34, 0x56, 0x78];
    
            if self.i != 0 {
                self.i -= 2;
    
                Some(T[((self.v >> self.i) & 0b11) as usize])
            } else {
                None
            }
        }
    }
    
    fn main() {
        let xs = [1, 2, 3, 4];
    
        let result: Vec<_> = xs.iter().copied().flat_map(NameMe::new).collect();
    
        let expect = [
            0x12, 0x12, 0x12, 0x34, 0x12, 0x12, 0x12, 0x56, 0x12, 0x12, 0x12, 0x78, 0x12, 0x12, 0x34,
            0x12,
        ];
    
        assert_eq!(result, expect);
    }
    

    【讨论】:

    • 在阅读此答案之前,我最终这样做了。很高兴你确认。谢谢。
    【解决方案2】:

    你不能只使用 Rust 1.49 稳定的标准库。

    每晚

    使用array::IntoIter:

    // 1.52.0-nightly (2021-02-09 097bc6a84f2280a889b9)
    use std::array;
    
    fn example() -> impl Iterator<Item = u8> {
        let data: [u8; 4] = [1, 2, 3, 4];
        array::IntoIter::new(data)
    }
    

    稳定的 Rust

    使用arrayvec:

    use arrayvec::ArrayVec; // 0.5.2
    
    fn example() -> impl Iterator<Item = u8> {
        let data: [u8; 4] = [1, 2, 3, 4];
        ArrayVec::from(data).into_iter()
    }
    

    应用它

    然后您可以将Iterator::flat_map 与任一解决方案一起使用:

    use arrayvec::ArrayVec; // 0.5.2
    
    fn example(data: [u8; 4]) -> impl Iterator<Item = u8> {
        ArrayVec::from(data).into_iter()
    }
    
    fn drive_it(i: impl Iterator<Item = [u8; 4]>) -> impl Iterator<Item = u8> {
        i.flat_map(example)
    }
    

    另见:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-06
      • 1970-01-01
      • 1970-01-01
      • 2011-03-24
      • 2020-05-18
      • 2021-05-14
      • 1970-01-01
      相关资源
      最近更新 更多