首页 > 解决方案 > 有条件地对 Rust 中的 Vec 进行排序

问题描述

假设我想对非克隆项目的 Vec 进行排序 - 但只是可能(这是我代码中问题的一个简化示例)。

我的尝试是这样的:

fn maybe_sort<T>(x: Vec<T>) -> Vec<T>
where
    T: std::cmp::Ord,
{
    // First, I need a copy of the vector - but only the vector, not the items inside
    let mut copied = x.iter().collect::<Vec<_>>();
    copied.sort();
    // In my actual code the line below depends on the sorted vec
    if rand::random() {
        return copied.into_iter().map(|x| *x).collect::<Vec<_>>();
    } else {
        return x;
    }
}

唉,借款检查员不高兴。我对 Vec 中的每个项目都有一个共享引用,尽管我从未返回对同一项目的 2 个引用,但 Rust 无法分辨。

有没有办法做到这一点unsafe?(如果没有,最干净的方法是unsafe.

标签: rustborrow-checker

解决方案


您可以.enumerate()将这些值保留为原始索引。您可以根据它的值对其T进行排序,并决定是返回排序后的版本,还是通过按原始索引排序来反转排序。

fn maybe_sort<T: Ord>(x: Vec<T>) -> Vec<T> {
    let mut items: Vec<_> = x.into_iter().enumerate().collect();
    items.sort_by(|(_, a), (_, b)| a.cmp(b));
    
    if rand::random() {
        // return items in current order
    }
    else {
        // undo the sort
        items.sort_by_key(|(index, _)| *index);
    }
    
    items.into_iter().map(|(_, value)| value).collect()
}

推荐阅读