Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In stable rust, how to move the minimum value out of an array, dropping the other values?

I have a fixed-size array [T; SIZE] of values of a type T that is ordered (it implements Ord, but not necessarily Clone or Default). I would like to extract the smallest value of the array and drop all the others.

In nightly rust, I can use array::IntoIter to achieve that, but if possible, I would like my code to compile on stable.

Currently, I'm using the following (playground):

    // Don't call this function if T has a custom Drop implementation or invalid bit patterns 
    unsafe fn get_min<T: Ord>(mut arr: [T; SIZE]) -> T {
        let (idx, _) = arr.iter().enumerate().min_by(|(_, x), (_, y)| x.cmp(y)).unwrap();
        unsafe { replace(&mut arr[idx],  MaybeUninit::uninit().assume_init()) }
    }

Of course, I'm not very happy with that... Is there a solution that is safer, and maybe less verbose ?

like image 874
lovasoa Avatar asked Jul 30 '20 09:07

lovasoa


People also ask

How do you append to an array in Rust?

There is no way to do this in stable Rust; arrays cannot have values added or removed at runtime; their lengths are fixed at compile time.

Does array implement copy Rust?

Arrays of any size implement the following traits if the element type allows it: Copy. Clone. Debug.

How do you copy an array in Rust?

In this article, we will see how to solve Copy An Array in rust code with examples. let arr =["a","b","c"]; // ES6 way const copy = [... arr]; // older method const copy = Array. from(arr);

How do you find the length of an array in Rust?

The length of an array is the number of elements present in the array. We use the len() function to obtain this value.


1 Answers

In the 2021 edition of Rust (available in Rust 1.56 and up), the into_iter() method on an array returns an iterator over the owned items, so this becomes easy:

fn get_min<T: Ord>(arr: [T; SIZE]) -> T {
    arr.into_iter().min().unwrap()     // assuming SIZE > 0
}

In earlier versions of Rust, you can move the minimum to the beginning of the array, and then use a slice pattern to move the first element out of the array:

fn get_min<T: Ord>(mut arr: [T; SIZE]) -> T {
    for i in 1..SIZE {
        if arr[i] < arr[0] {
            arr.swap(0, i);
        }
    }
    let [min, ..] = arr;
    min
}

(Playground)

Related questions:

  • How do I move values out of an array one at a time?
like image 183
Sven Marnach Avatar answered Oct 08 '22 16:10

Sven Marnach