如何将切片变成生锈的阵列?

时间:2021-10-02 15:39:35

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;