简体   繁体   中英

Converting a slice of arrays into an array of slices

I have a slice of fixed size arrays ( &[[T; N]] ), and I'd like to be able to view this as an array of slices ( [&[T]; N] ). The i -th element of the output array would be a slice of all of the i -th items from each array in the original slice:

fn magic_operation<T, const N: usize>(input: &[[T; N]]) -> [&[T]; N] {
    todo!()
}

let original = &[
    [10, 11, 12],
    [20, 21, 22],
    [30, 31, 32],
    [40, 41, 42],
    [50, 51, 52],
];

let new_view = magic_operation(original);

assert_eq!(new_view, [
    &[10, 20, 30, 40, 50],
    &[11, 21, 31, 41, 51],
    &[12, 22, 32, 42, 52],
]);

I don't know if this is exposed in any of the stdlib methods, and I don't know enough about unsafe Rust to try and approach this myself. Is this possible to achieve, perhaps with something like using slices with a different memory stride?

This is not possible.

Rust elements in a slice are contiguous; without extra spaces. In order to return a &[10, 20, 30, 40, 50] , then that sequence of elements must exist elsewhere to reference them as such. That sequence does not exist in the original input.

Slice of arrays to array of slices

If we're talking about safe code, then it's not possible to do this. With unsafe code you could return an array of slices, but it wouldn't be strictly a "view" into the data, we'd have to construct the data by copying values or references. This sort of unsafe coding is not likely something you need or want.


Rust Playground for examples below.

M x N Slice of arrays to N x M array of arrays

Below, the function is returning an array of arrays. The constraints on T were necessary to use T::default() as an initializer. Transforms the M x N array slice into an N x M array array.

fn magic_operation<T, const N: usize, 
                      const M: usize>(input: &[[T; N]; M]) -> [[T; M]; N] 
where T: Default + Copy,
{
    let mut v = [[T::default(); M]; N];
    
    for i in 0..M {
        for j in 0..N {
            v[j][i] = input[i][j];
        }
    }
    v
}

M x N Slice of arrays to N x M array of arrays of refs to original data

The second example shows the function returning an array of arrays of references to the original data. This didn't require constraining T because it's using the reference of the first value in input to initialize the new arrays - we could do that in the first example too if we wanted, which would eliminate the Default constraint on T .

fn magic_operation2<T, const N: usize, 
                       const M: usize>(input: &[[T; N]; M]) -> [[&T; M]; N] 
{
    let mut v = [[&input[0][0]; M]; N];
    
    for i in 0..M {
        for j in 0..N {
            v[j][i] = &input[i][j];
        }
    }
    v
}

There are also crates that have flexible ways of creating new arrays, array_init is one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM