zoukankan      html  css  js  c++  java
  • 学习 Rust cookbook 之算法篇(algorithm)part 2

    学习 Rust cookbook 之算法篇(algorithm)part 2

    上篇,我们了解了,可以用 rand crate 的接口进行生成随机数的操作,其中有生成指定类型的随机值,生成指定范围的随机值。这一篇,我们将探讨以下,从一堆元素中,随机获取其中一个的场景。

    场景

    获取自定义类型的随机值

    通常的做法是:假如有一个用户自定义的类型,针对其中的所有属性,挨个赋值随机值,这样得到的类型实例就相当于随机的了。但在 Rust 的 rand crate 中有一个独特的做法。

    按照 cookbook 中的介绍,已自定义类型 Point 为例,为 Standard 实现 Distribution<Point> trait。这里的 Distribution<Point> 在 Rust 中被称为“具象化”类型。嗯,名字听起来比较陌生,Java 中也有这个概念。不管这个概念,先实现一波:

    #[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,
            }
        }
    }
    
    pub fn test_point() {
        let mut rng = rand::thread_rng();
        let rand_point: Point = rng.gen();
        println!("random point is: {:#?}", rand_point);
    }
    

    从一堆随机的ASCII字符串中获取随机密码

    嗯,这也是一个比较常用的场景,比如验证码。。好吧,更多的我也暂时想不起来了。具体实现如下:

    /// 从字符串中获取随机密码
    pub fn get_random_string(length: u8) ->String {
        let mut rng = rand::thread_rng();
        let rand_str: String = rng.sample_iter(&Alphanumeric)
                    .take(length as usize)
                    .collect();
    
        return rand_str;
    }
    

    从给定的字符串中获取随机字符串

    这个和上方的实现类似,不同的是使用的是用户给定的字符串

    /// 从给定字符串中获取随机字符串
    pub fn get_random_string_from_customer_str(length: u8) -> String {
        let mut rng = rand::thread_rng();
        let customer_str: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ
                                    abcdefghijklmnopqrstuvwxyz
                                    0123456789)(*&^%$#@!~";
        let rand_str: String = (0..length)
                .map(|_| {
                    let idx = rng.gen_range(0, customer_str.len());
                    customer_str[idx] as char
                })
                .collect();
        rand_str
    }
    

    数组

    整数的排序

    Rust 中的数组类型是 std::vec::Vec。 通过宏 vec![] 可声明一个数组:

    let arr1 = vec![21,32,121, 90, 98, 67, 43];
    

    紧接着可以调用数组自带的排序方法: sort():

    arr1.sort();
    

    此时可以打印出排序后的数组:println!("the num is:{:?}", arr1);

    the num is:[21, 32, 43, 67, 90, 98, 121]

    浮点数的排序

    浮点数可以用上方的 sort 进行排序吗?大难是不能。不行你试试。

    试试就试试:

    let mut f1 = vec![21.0, 9.8, 21.5, 9.08, 72.1, 26.9];
    f1.sort();
    println!("{:?}", f1);
    

    编译时,编译器会提示:

    the trait std::cmp::Ord is not implemented for {float}

    在 cookbook 中,推荐的浮点数排序方式是使用 sort_by 方法。示例如下:

    let mut f1 = vec![21.0, 9.8, 21.5, 9.08, 72.1, 26.9];
    f1.sort_by(|a, b| {
        a.partial_cmp(b).unwrap()
    });
    println!("{:?}", f1);
    

    结构体数组的排序

    尝试了整数的排序、浮点数的排序,接下来,探索一下用户自定义类型数据的排序。一个结构体排序,一定是有依据的字段,比如数据库中,查询多条数据,拉取数据数据时,例如使用 order by id desc,其中的 id 就是排序的依据。那么我想,在 Rust 的结构体中,也应该是如此。cookbook 中的描述如下:

    对 Person 结构的 Vector 进行排序,通过属性name和age的自然顺序(按名称和年龄)。为了使 Person 可排序,你需要四个 traitEq,PartialEq,Ord和PartialOrd。可以简单地derive出这些特征。您还可以使用一个vec:sort_by方法,提供自定义比较函数:只按年龄排序。 ——《Rust cookbook》

    也就是说,我们有不止一种的方式对结构体数组排序,先来试试第一种 —— 对成员 derive 4 个 trait。我们的场景是学生考试分数相关。声明以下结构体:

    #[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
    struct StuResult {
        name: String,
        age: u8,
        score: u16,
    }
    

    分别实例化几个具体值,放入数组中,并调用 sort() 对数组排序:

    /// struct sort
    pub fn sort_for_struct() {
         let stu1 = StuResult {
            name: "Wali".to_string(),
            score: 0,
            age: 22,
        };
        let stu3 = StuResult {
            name: "Villian".to_string(),
            score: 0,
            age: 21,
        };
        let stu2 = StuResult {
            name: "Unita".to_string(),
            score: 0,
            age: 23,
        };
        let mut stus: Vec<StuResult> = vec!(stu1, stu2, stu3);
        println!("{:#?}", stus);
        stus.sort();
        println!("{:#?}", stus);
    }
    

    按照上方 cookbook 文中的描述,默认情况下,使用 stus.sort(); 是对结构体内部字段值进行自然排序,排序结果如下:

    [
        StuResult {
            name: "Unita",
            score: 0,
            age: 23,
        },
        StuResult {
            name: "Villian",
            score: 0,
            age: 21,
        },
        StuResult {
            name: "Wali",
            score: 0,
            age: 22,
        },
    ]
    

    如果你期望使用 age 进行排序,那么可以使用数组自带的 sort_by 方法:

    stus.sort_by(|a, b| a.age.cmp(&b.age));
    

    需要注意的是 sort_by 的参数是一个闭包 |a, b| a.age.cmp(&b.age), 该闭包的返回值类型是 Ordering。对 age 字段排序,运行结果如下:

    [
        StuResult {
            name: "Villian",
            score: 0,
            age: 21,
        },
        StuResult {
            name: "Wali",
            score: 0,
            age: 22,
        },
        StuResult {
            name: "Unita",
            score: 0,
            age: 23,
        },
    ]
    

    结果也如我们所期望,按照 age 的从小到大排序。

  • 相关阅读:
    TAOCP读书笔记——Search(1)
    JAVA进程间通信
    C++ Primer 阅读总结 (1)
    初来乍到
    [C#]手把手教你打造Socket的TCP通讯连接(二)
    [C#]手把手教你打造Socket的TCP通讯连接(三)
    数字ToString作为货币显示并且带小数
    [C#]手把手教你打造Socket的TCP通讯连接(一)
    [C#]手把手教你打造Socket的TCP通讯连接(四)
    WPF中使用ItemTemplate把所有Item都控制为指定大小
  • 原文地址:https://www.cnblogs.com/ishenghuo/p/12391461.html
Copyright © 2011-2022 走看看