una traza suma seleccionar sacar numeros matriz matrices letras inversa indexacion elementos con como calcular arreglos acceder arrays rust

arrays - traza - seleccionar elementos de una matriz matlab



¿Cómo obtener una rebanada como una matriz en Rust? (6)

Tengo una matriz de un tamaño desconocido, y me gustaría obtener una porción de esa matriz y convertirla en una matriz de tamaño estático:

fn pop(barry: &[u8]) -> [u8; 3] { barry[0..3] // mismatched types: expected `[u8, ..3]` but found `&[u8]` }

¿Cómo haría esto?


Aquí hay una función que coincide con la firma de tipo que pidió.

fn pop(barry: &[u8]) -> [u8; 3] { [barry[0], barry[1], barry[2]] }

Pero como barry podría tener menos de tres elementos, es posible que desee devolver una Option<[u8; 3]> Option<[u8; 3]> lugar de un [u8; 3] [u8; 3] .

fn pop(barry: &[u8]) -> Option<[u8; 3]> { if barry.len() < 3 { None } else { Some([barry[0], barry[1], barry[2]]) } }


Gracias a @malbarbo podemos usar esta función de ayuda:

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 }

para obtener una sintaxis mucho más ordenada:

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); }

siempre y cuando T: Default + Clone .

Si sabe que su tipo implementa Copy , puede usar este formulario:

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 }

Ambas variantes entrarán en panic! si la matriz de destino y el segmento pasado no tienen la misma longitud.


Puede crear manualmente la matriz y devolverla.

Aquí hay una función que puede escalar fácilmente si desea obtener más (o menos) de 3 elementos.

Tenga en cuenta que si el segmento es demasiado pequeño, los términos finales de la matriz serán 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 }


Puede crear una macro personalizada para resolver el problema. La restricción aquí, tiene que especificar el tamaño del sector como constante. No puede crear una matriz con longitud dinámica, lo que se explica en estas preguntas:

¿Cómo establecer dinámicamente una longitud de matriz Rust?

¿Es posible tener matrices asignadas a la pila con el tamaño determinado en el tiempo de ejecución en Rust?

macro_rules! slice_to_array { ($x:expr, $size:expr) => {{ let mut array = [0; $size]; array.copy_from_slice(&$x[..$size]); array }}; } fn main() { let vec = vec![1i64, 2, 3, 4, 5, 7]; let array = slice_to_array!(vec, 4); // It works fine // Attempt to use non-constant value in a constant // let size = 4; // let array = slice_to_array!(vec, size); println!("{:?}", array); }

Código de trabajo: zona de playground


Recomiendo usar el arrayref , que tiene una macro útil para hacer precisamente esto.

Tenga en cuenta que, al utilizar esta caja, creará una referencia a una matriz, &[u8; 3] &[u8; 3] , porque no clona ningún dato!

Si desea clonar los datos, puede seguir usando la macro, pero llamar a clonar al final:

#[macro_use] extern crate arrayref; fn pop(barry: &[u8]) -> &[u8; 3] { array_ref!(barry, 0, 3) }

o

#[macro_use] extern crate arrayref; fn pop(barry: &[u8]) -> [u8; 3] { array_ref!(barry, 0, 3).clone() }


¡Esta respuesta usa la función try_from inestable!

Puede hacerlo fácilmente con el nuevo rasgo TryInto (que aún es inestable a partir de junio de 2018):

fn pop(barry: &[u8]) -> [u8; 3] { barry.try_into() .map(|s: &[u8; 3]| s.clone()) .expect("slice with incorrect length") }

Pero aún mejor: ¡no hay necesidad de clonar tu matriz! En realidad, es posible obtener un &[u8; 3] &[u8; 3] de a &[u8] :

fn pop(barry: &[u8]) -> &[u8; 3] { barry.try_into().expect("slice with incorrect length") }

Como se mencionó en las otras respuestas, probablemente no querrás entrar en pánico si la longitud de barry no es 3, por lo que deberías devolver una Option<[u8; 3]> Option<[u8; 3]> o algo similar para manejar este error con gracia.

Esto funciona gracias a estas implementaciones (donde $N es solo un número entero entre 1 y 32) del rasgo relacionado TryFrom :

impl<''a, T> TryFrom<&''a [T]> for &''a [T; $N] type Error = TryFromSliceError;