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

Viewed 280

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 ?

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:

Related