You can easily do this with the TryInto trait (which was stabilized in Rust 1.34):
// Before Rust 2021, you need to import the trait:
// use std::convert::TryInto;
fn pop(barry: &[u8]) -> [u8; 3] {
barry.try_into().expect("slice should have length 3")
}
But even better: there is no need to clone/copy your elements! It is actually possible to get a &[u8; 3] from a &[u8]:
fn pop(barry: &[u8]) -> &[u8; 3] {
barry.try_into().expect("slice should have length 3")
}
As mentioned in the other answers, you probably don't want to panic if the length of barry is not 3, but instead handle this error gracefully.
This works thanks to these impls of the related trait TryFrom (before Rust 1.47, these only existed for arrays up to length 32):
impl<'_, T, const N: usize> TryFrom<&'_ [T]> for [T; N]
where
T: Copy,
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N]
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N]
Answer from Lukas Kalbertodt on Stack OverflowVideos
You can easily do this with the TryInto trait (which was stabilized in Rust 1.34):
// Before Rust 2021, you need to import the trait:
// use std::convert::TryInto;
fn pop(barry: &[u8]) -> [u8; 3] {
barry.try_into().expect("slice should have length 3")
}
But even better: there is no need to clone/copy your elements! It is actually possible to get a &[u8; 3] from a &[u8]:
fn pop(barry: &[u8]) -> &[u8; 3] {
barry.try_into().expect("slice should have length 3")
}
As mentioned in the other answers, you probably don't want to panic if the length of barry is not 3, but instead handle this error gracefully.
This works thanks to these impls of the related trait TryFrom (before Rust 1.47, these only existed for arrays up to length 32):
impl<'_, T, const N: usize> TryFrom<&'_ [T]> for [T; N]
where
T: Copy,
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N]
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N]
Thanks to @malbarbo we can use this helper function:
use std::convert::AsMut;
fn clone_into_array<A, T>(slice: &[T]) -> A
where
A: Default + AsMut<[T]>,
T: Clone,
{
let mut a = A::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.
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 = A::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.
I was playing around with 2d arrays in rust and wondered if there was a way to get python pandas like behaviour of slicing DataFrames in rust. I experimented with iterators a bit and came up with this. It's probably not the most elegant solution but might be nice in a pinch for beginners, also works on vectors:
fn main() {
let arr = [
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18],
[19, 20, 21, 22, 23, 24, 25, 26, 27],
[28, 29, 30, 31, 32, 33, 34, 35, 36],
[37, 38, 39, 40, 41, 42, 43, 44, 45],
[46, 47, 48, 49, 50, 51, 52, 53, 54],
[55, 56, 57, 58, 59, 60, 61, 62, 63],
[64, 65, 66, 67, 68, 69, 70, 71, 72],
[73, 74, 75, 76, 77, 78, 79, 80, 81],
];
//get the 4th row
let row = arr[3];
println!("row: {:?}", row);
//get the 6th column
let col = arr
.iter()
.map(|s| s.iter().nth(5).unwrap())
.collect::<Vec<_>>();
println!("col: {:?}", col);
//get a 4x4 slice starting at 2,2
let (x, y, z) = (2, 2, 4);
let slice = arr
.iter()
.skip(x)
.take(z)
.map(|s| s.iter().skip(y).take(z).collect::<Vec<_>>())
.collect::<Vec<_>>();
println!("slice: {:?}", slice);
//get a 5x5 slice starting at 1,1 and flatten into 1d vector
let (x, y, z) = (1, 1, 5);
let slice = arr
.iter()
.skip(x)
.take(z)
.map(|s| s.iter().skip(y).take(z).collect::<Vec<_>>())
.flatten()
.collect::<Vec<_>>();
println!("flat slice: {:?}", slice);
}Here is the output:
row: [28, 29, 30, 31, 32, 33, 34, 35, 36] col: [6, 15, 24, 33, 42, 51, 60, 69, 78] slice: [[21, 22, 23, 24], [30, 31, 32, 33], [39, 40, 41, 42], [48, 49, 50, 51]] flat slice: [11, 12, 13, 14, 15, 20, 21, 22, 23, 24, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42, 47, 48, 49, 50, 51]
If your rows are all of uniform width, it can be much easier to wrap a facade around a 1d structure than to have an actual 2d structure. I lost a lot of sleep in my youth trying to emulate the behavior of AppleSoft BASIC's multi-dimensional arrays before I realized that they were just a facade in front of a 1d array.
If you work a lot with multidimensional arrays, I also recommend the ndarray crate!