1. 生成随机值
需要安装rand
库,可通过cargo add rand
命令安装
[dependencies] rand = "0.8.5"
|
1.1 生成随机数
在随机数生成器 rand::Rng
的帮助下,通过 rand::thread_rng
生成随机数。可以开启多个线程,每个线程都有一个初始化的生成器。整数在其类型范围内均匀分布,浮点数是从 0
均匀分布到 1
,但不包括 1
。
use rand::Rng;
fn main() { let mut rng = rand::thread_rng();
let n1: u8 = rng.gen(); let n2: u16 = rng.gen(); println!("随机生成 u8: {}", n1); println!("随机生成 u16: {}", n2); println!("随机生成 u32: {}", rng.gen::<u32>()); println!("随机生成 i32: {}", rng.gen::<i32>()); println!("随机生成 float: {}", rng.gen::<f64>()); }
|
随机生成 u8: 158 随机生成 u16: 26703 随机生成 u32: 2989669353 随机生成 i32: -1944070083 随机生成 float: 0.6281595400384855
|
1.2 生成范围内随机数
使用 Rng::gen_range
,在半开放的 [0, 10)
范围内(不包括 10
)生成一个随机值。
use rand::Rng;
fn main() { let mut rng = rand::thread_rng(); println!("整型Integer: {}", rng.gen_range(0..10)); println!("浮点型Float: {}", rng.gen_range(0.0..10.0)); }
|
整型Integer: 7 浮点型Float: 4.609263483162893
|
使用 Uniform
模块可以得到均匀分布的值。下述代码和上述代码具有相同的效果,但在相同范围内重复生成数字时,下述代码性能可能会更好。
use rand::distributions::{Distribution, Uniform};
fn main() { let mut rng = rand::thread_rng(); let die = Uniform::from(1..7);
loop { let throw = die.sample(&mut rng); println!("掷骰子: {}", throw); if throw == 6 { break; } } }
|
掷骰子: 3 掷骰子: 1 掷骰子: 5 掷骰子: 4 掷骰子: 4 掷骰子: 5 掷骰子: 1 掷骰子: 4 掷骰子: 5 掷骰子: 5 掷骰子: 2 掷骰子: 5 掷骰子: 4 掷骰子: 1 掷骰子: 5 掷骰子: 4 掷骰子: 6
|
1.3 生成给定分布随机数
默认情况下,随机数在 rand
crate 中是均匀分布。rand_distr
(可通过cargo add rand_distr
安装) crate 提供其它的分布类型。如要使用,首先实例化一个分布,然后在随机数生成器rand::Rng
的帮助下,使用 Distribution::sample
从该分布中进行采样。如下是一个使用正态(Normal
)分布的实例
[dependencies] rand = "0.8.5" rand_distr = "0.4.3"
|
use rand_distr::{Distribution, Normal, NormalError}; use rand::thread_rng;
fn main() -> Result<(), NormalError> { let mut rng = thread_rng(); let normal = Normal::new(2.0, 3.0)?; let v = normal.sample(&mut rng); println!("{} 来自 N(2, 9) 分布", v); Ok(()) }
|
4.025748774397368 来自 N(2, 9) 分布
|
1.4 生成自定义类型随机值
随机生成一个元组 (i32, bool, f64)
和用户定义类型为 Point
的变量。为 Standard
实现 Distribution
trait
,以允许其随机生成。
use rand::Rng; use rand::distributions::{Distribution, Standard};
#[derive(Debug)] struct Point { x: i32, y: i32, }
impl Distribution<Point> for Standard { fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point { let (rand_x, rand_y) = rng.gen(); Point { x: rand_x, y: rand_y, } } }
fn main() { let mut rng = rand::thread_rng(); let rand_tuple = rng.gen::<(i32, bool, f64)>(); let rand_point: Point = rng.gen(); println!("随机元组: {:?}", rand_tuple); println!("随机坐标: {:?}", rand_point); }
|
随机元组: (-410099798, true, 0.3339881538362096) 随机坐标: Point { x: 1211748610, y: -959131956 }
|
1.5 从一组字母数字字符生成随机密码
随机生成一个给定长度的 ASCII
字符串,范围为 A-Z
,a-z
,0-9
,使用字母数字样本
use rand::{thread_rng, Rng}; use rand::distributions::Alphanumeric;
fn main() { let rand_string: String = thread_rng() .sample_iter(&Alphanumeric) .take(16) .map(char::from) .collect();
println!("随机密码: {}", rand_string); }
|
1.6 从一组用户定义字符创建随机密码
使用用户自定义的字节字符串,使用 gen_range
函数,随机生成一个给定长度的 ASCII
字符串
use rand::Rng; fn main() { const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789)(*&^%$#@!~"; const PASSWORD_LEN: usize = 16; let mut rng = rand::thread_rng();
let password: String = (0..PASSWORD_LEN) .map(|_| { let idx = rng.gen_range(0..CHARSET.len()); CHARSET[idx] as char }) .collect();
println!("指定字符随机密码: {}", password); }
|
指定字符随机密码: Rz!eVvWN)Xg5OYae
|
2. Vector
排序
2.1 整数 Vector
排序
通过 vec::sort
对一个整数 Vector
进行排序。另一种方法是使用 vec::sort_unstable
,后者运行速度更快一些,但不保持相等元素的顺序。
fn main() { let mut vec = vec![1, 5, 10, 2, 15]; vec.sort();
assert_eq!(vec, vec![1, 2, 5, 10, 15]); }
|
2.2 Vector
排序
对于f32
或 f64
的 vector,可以使用
vec::sort_by
和 PartialOrd::partial_cmp
对其进行排序
fn main() { let mut vec = vec![1.1, 1.15, 5.5, 1.123, 2.0];
vec.sort_by(|a, b| a.partial_cmp(b).unwrap());
assert_eq!(vec, vec![1.1, 1.123, 1.15, 2.0, 5.5]); }
|
2.3 结构体 Vector
排序
依据自然顺序(按名称和年龄),对具有 name
和 age
属性的 Person
结构体 Vector
排序。为了使 Person
可排序,需要添加traits
:PartialEq
。这样也可以使用 vec:sort_by
方法自定义比较函数,如按照年龄排序。
use std::cmp::Ordering;
#[derive(Debug, PartialEq)] struct Person { name: String, age: u32, salary: f64, }
impl Person { pub fn new(name: String, age: u32, salary: f64) -> Self { Person { name, age, salary } } }
fn main() { let mut people = vec![ Person::new("Zoe".to_string(), 25, 9483.54), Person::new("Al".to_string(), 60, 2433.64), Person::new("John".to_string(), 22, 6433.34), ];
people.sort_by(|a, b| a.name.cmp(&b.name)); assert_eq!( people, vec![ Person::new("Al".to_string(), 60, 2433.64), Person::new("John".to_string(), 22, 6433.34), Person::new("Zoe".to_string(), 25, 9483.54), ] );
people.sort_by(|a, b| a.age.cmp(&b.age));
assert_eq!( people, vec![ Person::new("John".to_string(), 22, 6433.34), Person::new("Zoe".to_string(), 25, 9483.54), Person::new("Al".to_string(), 60, 2433.64), ] ); people.sort_by(|a, b| b.salary.partial_cmp(&a.salary).unwrap_or(Ordering::Equal));
assert_eq!( people, vec![ Person::new("Zoe".to_string(), 25, 9483.54), Person::new("John".to_string(), 22, 6433.34), Person::new("Al".to_string(), 60, 2433.64), ] ); }
|