rust - 是否可以在不复制数据的情况下将 Vec<&[u8]> 展平为 &[u8] ?

我想展平包含 &[u8] 的矢量:

fn main() {
    let x: &[u8] = &b"abc"[..];
    let y: &[u8] = &b"def"[..];
    
    let z: Vec<&[u8]> = vec![x, y];
    
    println!("z: {:?}", z);
    
    let z_flat: &[u8] = z.into_iter().flatten().collect();
    
    println!("z_flat: {:?}", z_flat);
}

我得到编译器错误:

error[E0277]: a value of type `&[u8]` cannot be built from an iterator over elements of type `&u8`
 --> src/main.rs:9:49
  |
9 |     let z_flat: &[u8] = z.into_iter().flatten().collect();
  |                                                 ^^^^^^^ value of type `&[u8]` cannot be built from `std::iter::Iterator<Item=&u8>`
  |
  = help: the trait `FromIterator<&u8>` is not implemented for `&[u8]`

我也试过以下方法:

let z_flat: &[u8] = &z.into_iter().map(|x| x.to_vec()).flatten().collect();

编译错误:

error[E0277]: a value of type `[u8]` cannot be built from an iterator over elements of type `u8`
 --> src/main.rs:9:70
  |
9 |     let z_flat: &[u8] = &z.into_iter().map(|x| x.to_vec()).flatten().collect();
  |                                                                      ^^^^^^^ value of type `[u8]` cannot be built from `std::iter::Iterator<Item=u8>`
  |
  = help: the trait `FromIterator<u8>` is not implemented for `[u8]`

以下确实有效(playground):

let z_flat: &[u8] = &z.concat();

我无法使用 concat在我的实际应用程序中,因为我在检索嵌套字节( xy )时使用了另一个结构,并且此结构无法实现 Copy (仅 Clone )因为它包含一个 Vec<u8> field 。我有类似的东西 ( playground ):

#[derive(Clone, Debug)]
struct Foo {
    Bar: Vec<u8>,
}

impl Foo {
    fn baz(&self) -> Vec<u8> {
        self.Bar
    }
}

fn main() {
    let x = Foo { Bar: vec![8u8] };
    let y = Foo { Bar: vec![18u8] };

    let z: Vec<Foo> = vec![x, y];

    println!("z: {:?}", z);

    let z_flat = z
        .into_iter()
        .map(|x| &x.baz()[..])
        .collect::<Vec<&[u8]>>()
        .concat();

    println!("z_flat: {:?}", z_flat);
}

编译错误:

error[E0507]: cannot move out of `self.Bar` which is behind a shared reference
 --> src/main.rs:8:9
  |
8 |         self.Bar
  |         ^^^^^^^^ move occurs because `self.Bar` has type `Vec<u8>`, which does not implement the `Copy` trait

error[E0515]: cannot return value referencing temporary value
  --> src/main.rs:22:18
   |
22 |         .map(|x| &x.baz()[..])
   |                  ^-------^^^^
   |                  ||
   |                  |temporary value created here
   |                  returns a value referencing data owned by the current function

最佳答案

不,这是不可能的。根据定义,切片是一个连续的内存区域。你没有那个开始,所以你不能创建一个切片。

您的解决方法是将所有内容复制到一个连续的内存块中,然后您可以获取其中的一部分。我会这样写:

let z: Vec<&[u8]> = vec![b"abc", b"def"];
let z_alloc: Vec<u8> = z.iter().flat_map(|&x| x).copied().collect();
let z_flat: &[u8] = &z_alloc;

println!("z_flat: {:?}", z_flat);

对于更大的例子:

// fn baz(self) -> Vec<u8>
let z_flat: Vec<u8> = z.into_iter().flat_map(Foo::baz).collect();
// fn baz(&self) -> &[u8]
let z_flat: Vec<u8> = z.iter().flat_map(Foo::baz).copied().collect();

另见:

  • How to get a slice from an Iterator?

关于rust - 是否可以在不复制数据的情况下将 Vec<&[u8]> 展平为 &[u8] ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68625669/

相关文章:

c++ - 如何将 C 类型可变参数转换为 C++ 样式可变参数类型?

python - 如何创建嵌套列表并在每个嵌套中放置特定数量的元素?列表和它的嵌套元素总是不一样的

c++ - 来自具有大小的 char * 缓冲区的双向迭代器

typescript - 如何在 TypeScript 中有选择地将属性从一个对象复制到另一个对象

python - 正则表达式匹配尽可能少的字符

python - Django UUIDField 默认值

python - 在列表和元组列表之间查找公共(public) id

r - 如何过滤列中包含少于 3 个空格的行? (右)

angular - 如何以 Angular 重置表单组?

javascript - 我如何在 Next.js 中删除 ID 为 ="__next"的 div