如何从一个范围内创建一个 Vec 并对其进行洗牌?

83

我有以下代码:

extern crate rand;

use rand::{thread_rng, Rng};

fn main() {
    let mut vec: Vec<u32> = (0..10).collect();
    let mut slice: &[u32] = vec.as_mut_slice();

    thread_rng().shuffle(slice);
}

并且出现以下错误:
error[E0308]: mismatched types
 --> src/main.rs:9:26
  |
9 |     thread_rng().shuffle(slice);
  |                          ^^^^^ types differ in mutability
  |
  = note: expected type `&mut [_]`
             found type `&[u32]`

我认为向量和切片的内容是不可变的,这导致了这里的错误,但我不确定。 as_mut_slice 的签名是 pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T],所以该切片应该是可变的,但它却不是。
我知道一定有一个简单的解决方法,但我已经尽力了,但无法使其工作。
2个回答

118

Rand v0.6.0

Rng::shuffle 方法现已弃用; 应使用 rand::seq::SliceRandom trait。它在所有 slice 上提供了 shuffle() 方法,接受一个 Rng 实例:

// Rust edition 2018 no longer needs extern crate

use rand::thread_rng;
use rand::seq::SliceRandom;

fn main() {
    let mut vec: Vec<u32> = (0..10).collect();
    vec.shuffle(&mut thread_rng());
    println!("{:?}", vec);
}

在Playground上查看:链接.

原始回答

你非常接近了。这应该可以工作:

extern crate rand;

use rand::{thread_rng, Rng};

fn main() {
    let mut vec: Vec<u32> = (0..10).collect();
    let slice: &mut [u32] = &mut vec;

    thread_rng().shuffle(slice);
}

&mut [T]可以隐式转换为&[T],您在slice变量上注释了&[u32],因此该切片变为不可变:&mut [u32]被强制转换为&[u32]。这里变量上的mut不相关,因为切片只是借用其他人拥有的数据,所以它们没有继承的可变性-它们的可变性编码在它们的类型中。

实际上,您根本不需要在slice上进行注释。 这也可以正常工作:

extern crate rand;

use rand::{thread_rng, Rng};

fn main() {
    let mut vec: Vec<u32> = (0..10).collect();
    let slice = vec.as_mut_slice();

    thread_rng().shuffle(slice);
}

您甚至不需要中间变量:
extern crate rand;

use rand::{thread_rng, Rng};

fn main() {
    let mut vec: Vec<u32> = (0..10).collect();
    thread_rng().shuffle(&mut vec);
}

您应该阅读《Rust编程语言》,因为它解释了所有权和借用的概念以及它们如何与可变性交互。



谢谢你的回答。不幸的是,我把你的代码粘贴到 Rust Playground (https://play.rust-lang.org/) 中后发现 thread_rng().shuffle 已经被弃用了。你知道我们现在应该如何打乱一个向量吗?(我想我们应该使用一个trait,但我在 Rust 中还没有足够的经验来知道如何做到这一点。) - J-L
使用 rand 0.7.0 版本,Rng::shuffle 方法已被移除。现在需要使用 SliceRandom::shuffle 方法。 - Brooke Jackson

19

您可以像这样使用shuffle

extern crate rand;

use rand::Rng;

fn main() {
    let mut vec: Vec<usize> = (0..10).collect();
    println!("{:?}", vec);
    rand::thread_rng().shuffle(&mut vec);
    println!("{:?}", vec);
}

谢谢您的回答。不幸的是,我将您的代码粘贴到 Rust Playground (https://play.rust-lang.org/) 中后发现 thread_rng().shuffle 已经被弃用了。您知道我们现在应该如何打乱一个向量吗?(我认为我们应该使用一个 trait,但我在 Rust 中还没有足够的经验来知道如何做到这一点。) - J-L
这两个编译器警告似乎没有意义。
  • 其中一个警告是“未使用的变量:rng”,这显然是错误的,因为您在调用shuffle方法时正在使用rng。
  • 另一个警告说rng“变量不需要可变”,这也是错误的,因为我们需要在vec上调用shuffle时使用可变引用的rng。
- Brooke Jackson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接