如何从向量或数组中随机选择一个元素?

69

我有一个向量,其中的元素是 (String, String)。如何随机选择其中一个元素?

6个回答

105

你需要的是 rand crate,具体是其中的 choose 方法。

use rand::seq::SliceRandom; // 0.7.2

fn main() {
    let vs = vec![0, 1, 2, 3, 4];
    println!("{:?}", vs.choose(&mut rand::thread_rng()));
}

11
我不同意。这种方法与其他语言的唯一区别是需要将特性放在范围内,并手动指定随机数生成器状态的来源。可能比平常更加明确,但我认为还可以接受。 - Ethan McCue

20

使用choose_multiple方法:

use rand::seq::SliceRandom; // 0.7.2

fn main() {
    let samples = vec!["hi", "this", "is", "a", "test!"];
    let sample: Vec<_> = samples
        .choose_multiple(&mut rand::thread_rng(), 1)
        .collect();
    println!("{:?}", sample);
}

13
另一个加权采样的选择是已包含在rand库中的WeightedIndex。这里有一个示例: WeightedIndex
use rand::prelude::*;
use rand::distributions::WeightedIndex;

let choices = ['a', 'b', 'c'];
let weights = [2,   1,   1];
let dist = WeightedIndex::new(&weights).unwrap();
let mut rng = thread_rng();
for _ in 0..100 {
    // 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c'
    println!("{}", choices[dist.sample(&mut rng)]);
}

let items = [('a', 0), ('b', 3), ('c', 7)];
let dist2 = WeightedIndex::new(items.iter().map(|item| item.1)).unwrap();
for _ in 0..100 {
    // 0% chance to print 'a', 30% chance to print 'b', 70% chance to print 'c'
    println!("{}", items[dist2.sample(&mut rng)].0);
}

7

如果你想选择多个元素,那么random_choice 库可能适合你:

extern crate random_choice;
use self::random_choice::random_choice;

fn main() {
    let mut samples = vec!["hi", "this", "is", "a", "test!"];
    let weights: Vec<f64> = vec![5.6, 7.8, 9.7, 1.1, 2.0];

    let number_choices = 100;
    let choices = random_choice().random_choice_f64(&samples, &weights, number_choices);

    for choice in choices {
        print!("{}, ", choice);
    }
}

6
如果您还想要删除所选元素,这里有一种方法可以实现(使用rand crate):
let mut vec = vec![0,1,2,3,4,5,6,7,8,9];

let index = (rand::random::<f32>() * vec.len() as f32).floor() as usize;
let value = vec.remove( index );

println!("index: {} value: {}", index, value);
println!("{:?}", vec);

Rust Playground

remove(index)函数可以移除指定索引处的值(并将其后面的所有元素向左移动),然后返回该索引处的值(文档)。请注意,HTML标签应保留而不进行解释。


2

通过使用rng.gen_rangevec.get()的索引方法,还可以获取随机值。这也可以防止借用该值(在vec.choose()方法中会发生此情况)。

fn main() {
    let mut rng = rand::thread_rng();

    let my_strings : Vec<&str> = vec!["a", "b", "c"];
    let random_string_index: usize = rng.gen_range(0..my_strings.len());
    let string = my_strings[random_string_index];
    println!("{:?}", string);
}

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