rust 实用库
1 csv
use anyhow::Result;
use std::fs::{self, File};
fn main() -> Result<()> {
// 如果你是在 工作空间根目录下 执行 cargo run,
// 则这个csv文件需要相对于 工作空间根目录
let file = File::open("a.csv")?;
let mut csv = csv::Reader::from_reader(file);
// let headers = csv.headers()?.clone();
// println!("{:?}", headers);
for result in csv.records() {
let record = result?;
// let json_val = headers.iter().zip(record.iter()).collect::<Value>();
println!("{:?}", record);
println!("{:?}", record.get(0));
}
Ok(())
}2 serde1
use std::error::Error;
#[derive(Debug, serde::Deserialize)]
struct Record {
city: String,
region: u8,
country: String,
}
/* a.csv
tokyo,3,japan
beijing,1,china
*/
fn read_csv() -> Result<(), Box<dyn Error>> {
let file = std::fs::File::open("a.csv")?;
let mut rdr = csv::ReaderBuilder::new()
.has_headers(false) // 如果都是数据的情况, 设置没有 header
.from_reader(file);
for result in rdr.deserialize() {
// Notice that we need to provide a type hint for automatic
// deserialization.
let record: Record = result?;
println!("{}-{}", record.city, record.country);
}
Ok(())
}
/* a-with-header.csv
city,region,country
tokyo,3,japan
beijing,1,china
*/
fn read_csv_with_header() -> Result<(), Box<dyn Error>> {
let file = std::fs::File::open("a-with-header.csv")?;
let mut rdr = csv::ReaderBuilder::new()
.has_headers(true) // 如果是有header的情况, 设置true
.from_reader(file);
for result in rdr.deserialize() {
let record: Record = result?;
println!("{}-{}", record.city, record.country);
}
Ok(())
}
fn main() {
if let Err(err) = read_csv() {
println!("error running read_csv_with_header: {}", err);
}
if let Err(err) = read_csv_with_header() {
println!("error running read_csv_with_header: {}", err);
}
}
use serde::{Deserialize, Serialize};
// 使用 serde 的 derive 宏来为结构体自动实现序列化和反序列化
#[derive(Serialize, Deserialize, Debug)]
struct Person {
// rename可以设置json 格式的时候, 显示的名字
#[serde(rename = "user_name")]
name: String,
age: u8,
phones: Vec<String>,
}
fn main() {
// 创建一个 Person 实例
let person = Person {
name: "John Doe".to_string(),
age: 30,
phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()],
};
// 将 Person 实例序列化为 JSON 字符串
let serialized = serde_json::to_string(&person).unwrap();
println!("Serialized:\n{}", serialized);
// 将 JSON 字符串反序列化为 Person 实例
let deserialized: Person = serde_json::from_str(&serialized).unwrap();
println!("Deserialized:\n{:?}", deserialized);
}3 time
3.1 标准库里的time
fn main() {
use std::time::{Duration, SystemTime, UNIX_EPOCH};
let now = SystemTime::now();
println!("{:?}", now);
let now = SystemTime::now();
// UNIX_EPOCH: 1970/1/1
match now.duration_since(UNIX_EPOCH) {
Ok(elapsed) => {
println!("从 UNIX EPOCH 现在过去了 {} 秒", elapsed.as_secs());
}
Err(e) => {
println!("SystemTime 在 UNIX EPOCH 之前: {:?}", e);
}
}
use std::thread;
println!("程序开始");
// 休眠2s
thread::sleep(Duration::from_secs(2));
println!("程序结束");
let duration = now.elapsed();
println!("从获取now开始 到现在操作耗时: {:?}", duration);
let now2 = now.checked_add(Duration::from_secs(3));
println!("{:?}", now2);
}4 rand 随机数
extern crate rand; // 为了能在博客上能运行,这里需要加这句
use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
// 整数类型 生成的范围是 其类型范围内分布
let n1: u8 = rng.gen();
let n2: u16 = rng.gen();
println!("Random u8: {}", n1);
println!("Random u16: {}", n2);
println!("Random u32: {}", rng.gen::<u32>());
println!("Random i32: {}", rng.gen::<i32>());
// [0-1) 0到1区间(不包含1) 的浮点数
println!("Random float: {}", rng.gen::<f64>());
}extern crate rand;
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));
// 如果在相同范围内重复生成数字时, 下述代码性能可能会更好
use rand::distributions::{Distribution, Uniform};
let mut rng = rand::thread_rng();
let die = Uniform::from(1..7);
loop {
let throw = die.sample(&mut rng);
println!("Roll the die: {}", throw);
if throw == 6 {
break;
}
}
}
Caution
- 默认情况下, 随机数在 rand crate 中是均匀分布. rand_distr crate 提供其它的分布类型(比如正态分布)
- 关于这个分布类型, 自己网上了解, 这里简单说下
- 根据正态分布的68-95-99.7规则, 对于一个均值为μ、标准差为σ的正态分布, 以下是一些概率分布的近似情况:
- 大约68% 的数据值会落在均值的一个标准差范围内, 即在区间 [μ - σ, μ + σ] 内
- 大约95% 的数据值会落在均值的两个标准差范围内, 即在区间 [μ - 2σ, μ + 2σ] 内
- 大约99.7% 的数据值会落在均值的三个标准差范围内, 即在区间 [μ - 3σ, μ + 3σ] 内
- 在均值是0.0, 标准差是1.0 的正态分布 生成的随机数, 具体的分布情况:
- 大约68%的数据值会落在 [-1.0, 1.0] 的区间内
- 大约95%的数据值会落在 [-2.0, 2.0] 的区间内
- 大约99.7%的数据值会落在 [-3.0, 3.0] 的区间内
- 我在下面的代码中测试了该分布情况,确实如此
多执行几次看看
extern crate rand;
extern crate rand_distr;
use rand::thread_rng;
use rand_distr::{Distribution, Normal};
fn main() {
let (mut v1, mut v2, mut v3) = (0, 0, 0);
let mut rng = thread_rng();
// 均值是0.0, 标准差是1.0
let normal = Normal::new(0.0, 1.0).unwrap();
for _ in 0..100 {
// 循环100次
// 调用sample方法,使用rng生成一个符合正态分布的随机数,并将其绑定到变量v上
let v = normal.sample(&mut rng);
// println!("{} ", v);
if v >= -1.0 && v <= 1.0 {
v1 += 1;
}
if v >= -2.0 && v <= 2.0 {
v2 += 1;
}
if v >= -3.0 && v <= 3.0 {
v3 += 1;
}
}
println!("{}", v1);
println!("{}", v2);
println!("{}", v3);
}extern crate rand;
use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;
fn main() {
let rand_string: String = thread_rng()
.sample_iter(&Alphanumeric) // A-Z,a-z,0-9
.take(10) // 10位长度
.map(char::from)
.collect();
println!("{}", rand_string);
// 自定义字符
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789)(*&^%$#@!~";
const PASSWORD_LEN: usize = 10;
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);
}extern crate rand;
use rand::distributions::{Distribution, Standard};
use rand::Rng;
#[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)>();
// 需要为Standard实现 Distribution<Point> 这个trait 才可以这样
let rand_point: Point = rng.gen();
println!("Random tuple: {:?}", rand_tuple);
println!("Random Point: {:?}", rand_point);
}