有没有好的方法将Vec<T>转换为数组?

120
有没有一种好的方法将大小为S的Vec转换为类型为[T; S]的数组?具体来说,我正在使用一个返回128位哈希作为Vec的函数,它将始终具有长度16,并且我想将哈希处理为[u8, 16]。
是否有类似于as_slice方法的内置功能可以给我想要的结果,或者我应该编写自己的函数,分配固定大小的数组,迭代通过复制每个元素的向量,并返回数组?

3
使用itertools:Itertools,将其写成一行代码:my_array.iter_mut().set_from(my_vector.iter().cloned()); - don bright
@donbright 这会导致内存分配吗? - user2284570
很抱歉,我不太确定你的意思...你可以在这里查看生成的汇编代码(点击“Run”旁边的“...”,然后点击“ASM”):https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=088605093493b42833e08b8698841f20 - don bright
现在回顾这个问题,根据所使用的平台不同,用户可能会使用不安全的类型转换,理论上可以消除复制(内存分配?)并允许直接使用字节。 - don bright
as_chunks方法可以完成这个技巧。写下这段话时,它还处于试验阶段。 - Anssi
1个回答

116

数组必须完全初始化,因此当您将具有太多或太少元素的向量转换为数组时,您会迅速遇到问题。这些示例会简单地引发恐慌。

Rust 1.51开始,您可以根据数组的长度进行参数化。

use std::convert::TryInto;

fn demo<T, const N: usize>(v: Vec<T>) -> [T; N] {
    v.try_into()
        .unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len()))
}

截至 Rust 1.48版本,每个尺寸都需要专门的实现:
use std::convert::TryInto;

fn demo<T>(v: Vec<T>) -> [T; 4] {
    v.try_into()
        .unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", 4, v.len()))
}

截至 Rust 1.43:
use std::convert::TryInto;

fn demo<T>(v: Vec<T>) -> [T; 4] {
    let boxed_slice = v.into_boxed_slice();
    let boxed_array: Box<[T; 4]> = match boxed_slice.try_into() {
        Ok(ba) => ba,
        Err(o) => panic!("Expected a Vec of length {} but it was {}", 4, o.len()),
    };
    *boxed_array
}

另请参阅:


对我来说,这会失败并显示“trait `std::convert::From<std::boxed::Box<[T]>>` 未被实现为 `std::boxed::Box<[T; 3]>`。这是新的吗?(我提供的向量大小为3,并已相应更改了“demo”函数)。 - Alien_AV
1
@Alien_AV 对我有效 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接