如何交换数组的元素?

时间:2015-02-03 08:50:39

标签: rust

我想使用库函数交换切片data的元素,但由于多次借用它不起作用:

mem::swap(&mut data[i], &mut data[j]); //error

可以像往常一样手动完成:

let temp = data[i];
data[i] = data[j];
data[j] = temp;

但我不认为每次使用此代码都很棒。是否有任何其他解决方案通常使用库交换切片?

1 个答案:

答案 0 :(得分:19)

切片上有swap methoddata.swap(i, j)

原始代码不起作用,因为语言要求&mut不要别名,也就是说,如果可以通过&mut访问一段数据,则必须没有其他方法使用该数据。通常,对于连续索引data[i]data[j],编译器不能保证ij不同。如果它们是相同的,则索引指的是相同的内存,因此&mut data[i]&mut data[j]将是指向相同数据的两个指针:非法!

.swap在内部使用了一些unsafe代码,确保正确处理i == j大小写,避免别名&mut指针。也就是说,它不 使用unsafe,它只是为了确保这种“原始”操作具有高性能(我可以想象未来的语言/库改进会减少通过使需求不变量更容易表达,这里需要不安全,例如以下是一个安全的实施:

use std::cmp::Ordering;
use std::mem;

fn swap<T>(x: &mut [T], i: usize, j: usize) {
    let (lo, hi) = match i.cmp(&j) {
        // no swapping necessary
        Ordering::Equal => return,

        // get the smallest and largest of the two indices
        Ordering::Less => (i, j),
        Ordering::Greater => (j, i),
    };

    let (init, tail) = x.split_at_mut(hi);
    mem::swap(&mut init[lo], &mut tail[0]);
}

这里的关键是split_at_mut,它将切片分成两个不相交的半部分(这是在内部使用unsafe完成的,但Rust的标准库是在unsafe上构建的:该语言提供了“原始” “功能和库构建了其余部分。”