I have an array of an unknown size, and I would like to get a slice of that array and convert it to a statically sized array:
我有一个未知大小的数组,我想获得该数组的一个切片并将其转换为一个静态大小的数组:
fn pop(barry: &[u8]) -> [u8; 3] {
barry[0..3] // mismatched types: expected `[u8, ..3]` but found `&[u8]`
}
How would I do this?
我该怎么做呢?
5 个解决方案
#1
11
Here's a function that matches the type signature you asked for.
这里有一个与您要求的类型签名匹配的函数。
fn pop(barry: &[u8]) -> [u8; 3] {
[barry[0], barry[1], barry[2]]
}
But since barry
could have fewer than three elements, you may want to return an Option<[u8; 3]>
rather than a [u8; 3]
.
但是由于barry的元素可能少于3个,您可能想返回一个选项<[u8;3) >而不是a [u8];3)。
fn pop(barry: &[u8]) -> Option<[u8; 3]> {
if barry.len() < 3 {
None
} else {
Some([barry[0], barry[1], barry[2]])
}
}
#2
14
Thanks to @malbarbo we can use this helper function:
感谢@malbarbo,我们可以使用这个助手功能:
use std::convert::AsMut;
fn clone_into_array<A, T>(slice: &[T]) -> A
where
A: Default + AsMut<[T]>,
T: Clone,
{
let mut a = Default::default();
<A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
a
}
to get a much neater syntax:
要获得更整洁的语法:
fn main() {
let original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let e = Example {
a: clone_into_array(&original[0..4]),
b: clone_into_array(&original[4..10]),
};
println!("{:?}", e);
}
as long as T: Default + Clone
.
只要T:默认+克隆。
If you know your type implements Copy
, you can use this form:
如果你知道你的类型实现复制,你可以使用这个表格:
use std::convert::AsMut;
fn copy_into_array<A, T>(slice: &[T]) -> A
where
A: Default + AsMut<[T]>,
T: Copy,
{
let mut a = Default::default();
<A as AsMut<[T]>>::as_mut(&mut a).copy_from_slice(slice);
a
}
Both variants will panic!
if the target array and the passed-in slice do not have the same length.
两种变体将恐慌!如果目标数组和传入的片没有相同的长度。
#3
10
I recommend using the crate arrayref, which has a handy macro for doing just this.
我建议使用crate arrayref,它有一个方便的宏来实现这一点。
Note that, using this crate, you create a reference to an array, &[u8; 3]
, because it doesn't clone any data!
注意,使用这个板条箱创建对数组的引用&[u8;因为它不克隆任何数据!
If you do want to clone the data, then you can still use the macro, but call clone at the end:
如果您确实想要克隆数据,那么您仍然可以使用宏,但是最后调用clone:
#[macro_use]
extern crate arrayref;
fn pop(barry: &[u8]) -> &[u8; 3] {
array_ref!(barry, 0, 3)
}
or
或
#[macro_use]
extern crate arrayref;
fn pop(barry: &[u8]) -> [u8; 3] {
array_ref!(barry, 0, 3).clone()
}
#4
8
You can manually create the array and return it.
您可以手动创建数组并返回它。
Here is a function that can easily scale if you want to get more (or less) than 3 elements.
如果您想获得多于(或少于)3个元素,这个函数可以轻松伸缩。
Note that if the slice is too small, the end terms of the array will be 0's.
注意,如果切片太小,数组的最后项将是0。
fn pop(barry: &[u8]) -> [u8; 3] {
let mut array = [0u8; 3];
for (&x, p) in barry.iter().zip(array.iter_mut()) {
*p = x;
}
array
}
#5
4
This answer uses the unstable try_from
feature!
这个答案使用了不稳定的try_from特性!
You can easily do this with the brand new TryInto
trait (which is still unstable as of June 2018):
你可以用全新的TryInto特性(到2018年6月仍然不稳定)来做这件事:
fn pop(barry: &[u8]) -> [u8; 3] {
barry.try_into()
.map(|s: &[u8; 3]| s.clone())
.expect("slice with incorrect length")
}
But even better: there is no need to clone your array! It is actually possible to get a &[u8; 3]
from a &[u8]
:
但更好的是:没有必要克隆您的数组!实际上可以得到&[u8;3)从&(与):
fn pop(barry: &[u8]) -> &[u8; 3] {
barry.try_into().expect("slice with incorrect length")
}
As mentioned in the other answers, you probably don't want to panic if the length of barry
is not 3, so you should return an Option<[u8; 3]>
or something similar to handle this error gracefully.
正如在其他答案中提到的,如果barry的长度不是3,您可能不想恐慌,所以应该返回一个选项<[u8];3]>或类似的处理这个错误的方法。
This works thanks to these impls (where $N
is just an integer between 1 and 32) of the related trait TryFrom
:
这得益于相关特征TryFrom的这些impls(其中$N只是1到32之间的整数):
impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N]
type Error = TryFromSliceError;
#1
11
Here's a function that matches the type signature you asked for.
这里有一个与您要求的类型签名匹配的函数。
fn pop(barry: &[u8]) -> [u8; 3] {
[barry[0], barry[1], barry[2]]
}
But since barry
could have fewer than three elements, you may want to return an Option<[u8; 3]>
rather than a [u8; 3]
.
但是由于barry的元素可能少于3个,您可能想返回一个选项<[u8;3) >而不是a [u8];3)。
fn pop(barry: &[u8]) -> Option<[u8; 3]> {
if barry.len() < 3 {
None
} else {
Some([barry[0], barry[1], barry[2]])
}
}
#2
14
Thanks to @malbarbo we can use this helper function:
感谢@malbarbo,我们可以使用这个助手功能:
use std::convert::AsMut;
fn clone_into_array<A, T>(slice: &[T]) -> A
where
A: Default + AsMut<[T]>,
T: Clone,
{
let mut a = Default::default();
<A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
a
}
to get a much neater syntax:
要获得更整洁的语法:
fn main() {
let original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let e = Example {
a: clone_into_array(&original[0..4]),
b: clone_into_array(&original[4..10]),
};
println!("{:?}", e);
}
as long as T: Default + Clone
.
只要T:默认+克隆。
If you know your type implements Copy
, you can use this form:
如果你知道你的类型实现复制,你可以使用这个表格:
use std::convert::AsMut;
fn copy_into_array<A, T>(slice: &[T]) -> A
where
A: Default + AsMut<[T]>,
T: Copy,
{
let mut a = Default::default();
<A as AsMut<[T]>>::as_mut(&mut a).copy_from_slice(slice);
a
}
Both variants will panic!
if the target array and the passed-in slice do not have the same length.
两种变体将恐慌!如果目标数组和传入的片没有相同的长度。
#3
10
I recommend using the crate arrayref, which has a handy macro for doing just this.
我建议使用crate arrayref,它有一个方便的宏来实现这一点。
Note that, using this crate, you create a reference to an array, &[u8; 3]
, because it doesn't clone any data!
注意,使用这个板条箱创建对数组的引用&[u8;因为它不克隆任何数据!
If you do want to clone the data, then you can still use the macro, but call clone at the end:
如果您确实想要克隆数据,那么您仍然可以使用宏,但是最后调用clone:
#[macro_use]
extern crate arrayref;
fn pop(barry: &[u8]) -> &[u8; 3] {
array_ref!(barry, 0, 3)
}
or
或
#[macro_use]
extern crate arrayref;
fn pop(barry: &[u8]) -> [u8; 3] {
array_ref!(barry, 0, 3).clone()
}
#4
8
You can manually create the array and return it.
您可以手动创建数组并返回它。
Here is a function that can easily scale if you want to get more (or less) than 3 elements.
如果您想获得多于(或少于)3个元素,这个函数可以轻松伸缩。
Note that if the slice is too small, the end terms of the array will be 0's.
注意,如果切片太小,数组的最后项将是0。
fn pop(barry: &[u8]) -> [u8; 3] {
let mut array = [0u8; 3];
for (&x, p) in barry.iter().zip(array.iter_mut()) {
*p = x;
}
array
}
#5
4
This answer uses the unstable try_from
feature!
这个答案使用了不稳定的try_from特性!
You can easily do this with the brand new TryInto
trait (which is still unstable as of June 2018):
你可以用全新的TryInto特性(到2018年6月仍然不稳定)来做这件事:
fn pop(barry: &[u8]) -> [u8; 3] {
barry.try_into()
.map(|s: &[u8; 3]| s.clone())
.expect("slice with incorrect length")
}
But even better: there is no need to clone your array! It is actually possible to get a &[u8; 3]
from a &[u8]
:
但更好的是:没有必要克隆您的数组!实际上可以得到&[u8;3)从&(与):
fn pop(barry: &[u8]) -> &[u8; 3] {
barry.try_into().expect("slice with incorrect length")
}
As mentioned in the other answers, you probably don't want to panic if the length of barry
is not 3, so you should return an Option<[u8; 3]>
or something similar to handle this error gracefully.
正如在其他答案中提到的,如果barry的长度不是3,您可能不想恐慌,所以应该返回一个选项<[u8];3]>或类似的处理这个错误的方法。
This works thanks to these impls (where $N
is just an integer between 1 and 32) of the related trait TryFrom
:
这得益于相关特征TryFrom的这些impls(其中$N只是1到32之间的整数):
impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N]
type Error = TryFromSliceError;