Как создать Vec из диапазона и перетасовать его?

У меня есть следующий код:

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], поэтому срез должен быть изменяемым, но это как-то не так.

Я знаю, что это должно быть легко исправить, но я старался изо всех сил и не мог заставить его работать.

Ответ 1

Ты очень близко Это должно работать:

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], и вы &[u32] переменную 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);
}

Вам следует прочитать The Rust Programming Language, поскольку он объясняет концепции владения и заимствования и как они взаимодействуют с изменчивостью.


Обновление: начиная с ранда v0.6.0, метод Rng::shuffle устарел. Вместо этого следует использовать черту rand::seq::SliceRandom. Он предоставляет метод 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);
}

Смотрите это на детской площадке.

Ответ 2

Вы можете использовать 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);
}