rust 实用库

Created

2024-09-13 13:39:46

Updated

2024-10-31 20:13:58

1 csv

cargo add 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

cargo add serde --features derive
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);
    }
}
cargo add serde_json
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 随机数

添加库
cargo add 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] 的区间内
    • 我在下面的代码中测试了该分布情况,确实如此
添加rand_distr库
cargo add rand_distr
多执行几次看看
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);
}
Back to top