Rust 学习3, 枚举,集合
Option枚举
Option定义于标准库中,并且会与导入(我们不需要主动引入), 描述了某个值可能存在(某种类型)或不存在的情况
// 4月16日每日一题
//给定一个整数 n ,返回 可表示为两个 n 位整数乘积的 最大回文整数 。因为答案可能非常大,所以返回它对 1337 取余 。
// Debug De到我死,现在每天每日一题加上Rust刷真的,有点东西。
// 但是和下面的Python比性能瞬间就上来了
//执行用时: 88 ms
//内存消耗: 2.1 MB
impl Solution {pub fn largest_palindrome(n: i32) -> i32 {if (n == 1) {return 9;}let mut p1 = n;let mut start:u32 = 1;// 没找到指数运算符,只能用这种最古老的写法while (p1 > 0){start = start * 10;p1 = p1 - 1;}let end = start/10 ;// 第一个循环回文数枚举for huiwen in (end..start).rev(){let huiwen_rev = huiwen.to_string();let mut huiwen2 = huiwen_rev.clone();// 是真的菜啊,学Rust的第三天,一段字符串逆向的代码写了半年let huiwen_chars = huiwen_rev.chars();for letter in huiwen_chars.rev(){let num_wei = letter.to_string();huiwen2 = huiwen2 + &num_wei;}//之所以转u64是因为132我略微看了一眼 n=8 的时侯相乘和回文数都会会越界,,所以没办法,最后在强转一下,,let huiwen_num:u64 = huiwen2.trim().parse().expect("Something wrong");// 第二重循环, 找因数let mut starts = (start - 1) as u64;//这里也是,应该用平方个但我比不知道咋用就只能这么写,,脑子已经被驴踢了while (starts * starts >= huiwen_num){if (huiwen_num % starts == 0){let p:i32 = (huiwen_num/starts).to_string().len() as i32;if (p == n){let h = (huiwen_num % 1337) as i32;println!("{}",h);return h;} }starts = starts - 1}} }
}
# 同样思路的Python代码,我看着这简单的代码只能说世界的参差。
# 哦,但是Python性能太拉了
# 执行用时: 2136 ms
# 内存消耗: 15 MB
class Solution:def largestPalindrome(self, n: int) -> int:if n == 1:return 9else:for huiwen in range(10**n - 1,10**(n-1) - 1, -1):k = str(huiwen)k = k[::-1]huiwen = eval(str(huiwen) + k)m = int(huiwen**(1/2))for p in range(10**n - 1,m,-1):if huiwen % p == 0 and (huiwen / p >= 10 **(n-1) and huiwen / p < 10 ** n):return huiwen % 1337
Rust中没有NULL的概念,取而代之的是使用Options的枚举, 主要是放置Null值泛滥
// 会遇到如,源码如下,我们使用的时候直接使用即可
//enum Option<T>{// Some(T),
// None,
//}
// 使用
fn main(){// Some无需显示声明let p = Some("Hello Google");// 这里一定要知名类型是Option<i32>, 编译器无法解析到let q: Option<i32> = None;println!("{:?},{:?}",p,q);
}
Some("Hello Google"),None
Match控制流
match是Rust中功能最为强大的控制流之一, 包括我们前面l利用match优雅的代替except的过程, 简直就是我的超人 它允许:
- 一个值和一系列模式进行匹配,并执行匹配的模式对应的代码
- 模式可以是字面值,变量名, 通配符等等
// 还是用上面Sex的枚举做例子
// 用引用的时候参数变成 & Sex类型
fn judge_boy_or_girl(sex: Sex) -> String{match sex{// 这里的横线是因为我定义的类型是Vec,集合类型,需要绑定值操作Sex::male(_) => String::from("He is a male"),Sex::female(_) => String::from ("She is a female"),}
}
// 同样的,这里传递玩参数也会时区所有权,我们可以用引用的方式,&boy, &girl
println!("{}",judge_boy_or_girl(boy));
println!("{}",judge_boy_or_girl(girl));
He is a male
She is a female
- 匹配的分支可以绑定被匹配到的对象的部分值,因此可以从enum变体中提取值, 或用可变引用修改.
fn print_sex(sex: & mut Sex) -> String{return match sex {Sex::male(character) => {character.push(String::from("Boy"));String::from("He is a male")},Sex::female(character) => {character.push(String::from("Girl"));String::from("She is a female")},}
}
println!("{}",print_sex(& mut boy));
println!("{}",print_sex(& mut girl));
println!("{:?}", boy);
println!("{:?}",girl);
He is a male
She is a female
male(["dicks", "Adam's apple ", "Boy"])
female(["burst", "Menstrual cycle:", "Girl"])
Match匹配的时候必须穷举所有的枚举项,毕竟是枚举类型嘛,可以理解.当然, 我们可以使用通配符"_"来代替没出没的值减少我们的麻烦:
#[derive(Debug)]
enum College_Student{benke(String),yanjiusheng(String),boshisheng(String),
}
impl College_Student{fn am_I_a_benke(&self) -> bool{match self{College_Student::benke(_)=> true,_=>false,}}
}fn main(){let me = College_Student::benke(String::from("非人大学"));let brother = College_Student::yanjiusheng(String::from("迪士尼马猴烧酒大学"));println!("{}", me.am_I_a_benke());println!("{}", brother.am_I_a_benke());
}
true
false
Package, Crete, Module
Rust的代码组织包括:哪些细节可以暴漏,哪些细节私有,作用域内的哪些名称有效,这些功能在Rust中统称为模块系统,包括:
Package (最顶层) : Cargo的特性, 让我们构建,测试,共享crate
Crate(单元包) : 一个模块树, 产生一个Libuary或二进制习惯文件
Module (模块) : 让你控制代码的组织,作用域与私有路径
Path (路径) ** : 为struct fuction module 等项命名的方式**
Crate
类型: binary 二进制可执行文件, library: 类似于dll的库文件
Crate ROOT:
- 源代码编译文件, RUST编译器从这里开始组成你的Crate的跟Module
作用: 将相关的功能组合到一个作用域内, 便于在项目间进行共享
Package
- 只包含一个Cargo.toml , 描述了如何构建Crates
- 只能包含0~1个 Library crate
- 可以包含任意数量的binary crate
- 必须至少包含一个crate
# 还是这颗文件树比较清晰
G:.
│ .gitignore# Cargo创建项目自动生成的文件,负责追踪项目依赖的精确版本,不需要手动更改
│ Cargo.lock
| # Cargo配置文件,使用Toml格式, 默认将src/main.re作为crate root, crate名字与package的名字相同
│ Cargo.toml
│
├─src # 生成一个带main函数的代码文件
│ main.rs
| # package包含一个linrary crate, 这个文件式library crate的 crate root,crate名字与package的名字相同
| (假如包含lib.rs)
└─target│ .rustc_info.json│ CACHEDIR.TAG└─debug
Cargo 会把我们上面两个有可能出现crate root的部分交给 rustc构建libruary 或binary
Cargo 会把binary crate放在 src/bin目录下面
Module
控制作用域和私有性, 在一个crate内将代码进行分组, 增加可读性易于复用, 控制项目(item)的私有性(public,private)
建立 module:
mode关键字, 可嵌套, 可以包含其他项(struct,enum,常量,trait, 函数等)
// 在lib.rs中的一个简单的例子
mod classroom{// 一教mod Oneclass{fn findA_space() -> String{String::from("A113")}fn findB_space() -> String{String::from("B305")}fn findC_space() -> String{String::from("C209")}fn findD_space() -> String{String::from("No Space")}}// 综合楼mod Complex{enum Classroom {// 综合楼B座空教室列表B(Vec<String>),// 综合楼C座空教室列表C(Vec<String>),// 综合楼行政楼空教室列表,当然,绝对是Nonebouleuterion(Option<String>),}}
}
#所以他的命名空间树形应该长这样, 虽然丑但是我尽力了.
crate|____classroom|________one_class| |____findA_space| |____findB_space| |____findC_space| |____findD_space||________complex|_______classroom|______B|______C|______bouleuterion
Path
而我们这样画出来了这个树形图可不是白画的,因为我们要想访问这些东西,就要访问它的路径.
路径的使用可以有两种方式:绝对路径与相对路径
绝对路径,从上图路径crate ( crate的root) 开始, 使用crate名或字面值
相对路径: 从当前模块开始,使用 self,super或模块当前的标识符
路径至少 由一个标识符组成, 标识符之间使用::
// 一个例子
fn example(){let find_a = crate::classroom::one_class::findA_space();println!("{}",find_a);let space_bo = crate::classroom::complex::Classroom::bouleuterion(None);let space_C = crate::classroom::complex::Classroom::C(vec![String::from("C304"),String::from("C208")]);println!("{:?},{:?}",space_bo,space_C);
}
25 | let find_a = crate::classroom::one_class::findA_space();| ^^^^^^^^^^^ private function
上面看到我的演示报了个error, 为什么呢, 看这个错,说这个东西是private fuction, 看着很熟悉.Rust中这种现象叫私有边界,或者我们就可以理解为封装.
私有边界/ 封装
模块不仅可以组织代码,还可以顶以私有边界.Rust中默认所有条目是private的,所以我们定义的时候需要在函数前加上pub代表这是一个piblic的函数.
注意:父级模块无法访问子级模块中的私有条目,但是子级模块可以访问父级模块所有条目
值得注意的是, 对于struct允许细化管理其中的属性的公私有(默认私有) 但是enum一旦共有则其定义全部类型均为共有
Use
引入包的时候我们使用use关键字.
感觉没啥,除了我们熟悉的.全部变成:: 和路径用上面的方法去找之外没什么难的,哦,use也可以使用as, 没了
使用外部包, 修改Cargo.toml, 上官网去复制配置即可. 用Use引入模块我们就可以使用了.
use支持嵌套路径 在 同一行内 将条目引入, 也支持通配符*
//eg.
use std::{cmp::Ordering,io,......};
use std::io::*;
最后,我们想在我们的main.rs中使用我们lib 或其他任意文件中定义的这些模块,只需要用mod + 文件名; 声明使用即可, 这样编译器就会找src文件夹下面的文件.如果层级间的文件创建引用的话需要建更多目录保证层级关系一致
//lib.rs
pub mod classroom{// 一教pub mod one_class {pub fn findA_space() -> String{String::from("A113")}fn findB_space() -> String{String::from("B305")}fn findC_space() -> String{String::from("C209")}fn findD_space() -> String{String::from("No Space")}}// 综合楼pub mod complex {#[derive(Debug)]pub enum Classroom {// 综合楼B座空教室列表B(Vec<String>),// 综合楼C座空教室列表C(Vec<String>),// 综合楼行政楼空教室列表,当然,绝对是Nonebouleuterion(Option<String>),}}
}//main.rs
mod lib;
use lib::classroom::*;
fn main(){let find_a =one_class::findA_space();println!("{}",find_a);let space_bo =complex::Classroom::bouleuterion(None);let space_C = complex::Classroom::C(vec![String::from("C304"),String::from("C208")]);println!("{:?},{:?}",space_bo,space_C);
}
A113
bouleuterion(None),C(["C304", "C208"])
常用的集合(Heap上动态大小)
Vector
Vector其实我们之前介绍过,在定义某些类型的时候也用过,是一个长度自由变换的数组.这这里我们做一个较详细的介绍
Vec , vector, 是由标准库提供的, 可存储多个值但只能存储相同类型的数据的一种结构, 其存储值在内存中连续存放
// vector.rs
pub mod vector{pub fn create_i32_vector() -> Vec<i32>{// 这里的初识话必须知名类型,无法返回Vec<?>这样的类型let m:Vec<i32> = Vec::new();// 当然,我们前面用的vec!宏的方式创建的,比如// let new_vec:Vec<i8> = vec![10, 20, 30];return m;}
}
// main.rs
mod vector;
use vector::vector as vectors;
fn main() {let m = vectors::create_i32_vector();println!("{:?}",m);
}
[]
向Vector做增删改 (对Vec索引用[]): push 增, pop 删/ remove删索引, 使用[]索引修改, 使用索引或get 进行查(get 遇到越界不会像[] panic, 而是返回None)
fn main() {let mut m = vectors::create_i32_vector();m.push(10);m.push(30);m.push(20);m[0] = 5;m.remove(2);let n = m[m.len() - 1];m.pop();println!("{},{:?}",n,m);
}
30,[5]
Vector可以用for轻松遍历:
// 两种都可
pub fn iter_vector(vecs:& Vec<i32>){for i in vecs.iter(){println!("{}",i);}for &k in vecs{println!("{}",k);}
}
虽然Vector只能存放相同的数据,但是我们可以利用枚举类型可以不加不同类型数据这一点定义同一枚举下的附加不同数据来达到存储多种数据的目的 (毕竟是指针嘛,也算是同一类型,问题不大,这个方法真的是妙诀
#[derive(Debug)]
enum Student{name(String),age(u8),hobby(Vec<String>),study_good(bool),
}
fn main() {let my_name = Student::name(String::from("Hello"));let my_age = Student::age(69);let my_hobby = Student::hobby(vec![String::from("Rust"), "Python".to_string()]);let my_study = Student::study_good(false);let mut m = Vec::new();m.push(my_name);m.push(my_age);m.push(my_hobby);m.push(my_study);println!("{:?}",m);for iters in m.iter(){match iters{Student::name(a) =>{print!("{} ",a);},Student::age(a) =>{print!("{} ",a);},Student::hobby(a) => {print!("{:?} ",a)}Student::study_good(a) => {print!("{} ",a);},};}
}
[name("Hello"), age(69), hobby(["Rust", "Python"]), study_good(false)]
Hello 69 ["Rust", "Python"] false
String
学一个东西肯定要从定义学起,字符串就是Byte的集合, 并提供了一些方法将字节解析为文本
在Rust的核心语言层面 只有一个字符串类型: 字符串切片str/&str . 字符串切片,就是对存储在其它地方、UTF8编码的字符串引用. 而我们所说所用的String类型,来自标准库而不是核心语言,可增长,可修改,有所有权
的采用UTF8编码的类型.
我们所说的Rust的字符串并不是单指一种,而是String 与&str两种都是. 这两种在便准苦衷使用的最多,且都是用UTF8编码.(Rust还提供很多其他的字符串类型)
其实我再前面所有权的规则和切片都有放过Dtring类型的底层数据结构的图片区方便我们理解.String最大的好处就是所有的基础数据类型/标量类型 ,都可以无条件转String,就这么强大和牛逼给你你不用?反正我是一定会用的.
fn main(){let a = 1;let b:u128 = 2;let c = 10.99;let d:char = 'a';let e:&str = "hello";let f = false;a.to_string();b.to_string();c.to_string();d.to_string();e.to_string();f.to_string();println!("{} {} {} {} {} {}",a,b,c,d,e,f);
}
1 2 10.99 a hello false
几个实用的方法:
// 增加
fn main(){let mut a = String::from("Hello");a.push_str(" Google");a.push('
Rust 学习3, 枚举,集合相关推荐
- Rust学习:14_包和模块
Rust学习:14_包和模块 前言 为了学习Rust,阅读了github上的Rust By Practice电子书,本文章只是用来记录自己的学习过程,感兴趣的可以阅读原书,希望大家都能掌握Rust! ...
- rust学习笔记中级篇1–泛型(霜之小刀)
rust学习笔记中级篇1–泛型(霜之小刀) 欢迎转载和引用,若有问题请联系 若有疑问,请联系 Email : lihn1011@163.com QQ:2279557541 结构体泛型 首先上代码,如何 ...
- [Rust学习:四] Vec和栈
[Rust学习:四] Vec和栈 一.前言 二.阅读Vec源码尝试常用接口. 1. 创建Vec 2. 在尾部添加push\extend\append 3. 任意位置添加insert 4. 在尾部删除p ...
- MATLAB中深度学习的数据集合
简 介: 本文总结了部分MATLAB中用于深度学习的数据集合. 关键词: MATLAB,DEEPLENARING #mermaid-svg-xPWl4yTsAw5Z4HFe {font-family: ...
- Python学习笔记:集合(set)
Python学习笔记:集合(set) 1.集合概念 集合是互异元素的无序集合.类似于只有键没有值的字典. 2.创建集合 有两种方法创建集合:一个是利用set函数,一个是利用花括号创建集合字面量. 3. ...
- c语言如何宏定义枚举型结构体,C语言学习笔记--枚举结构体
枚举 枚举是一种用户定义的数据类型,它用关键字enum以如下语法格式来声明: enum 枚举类型名字 {名字0,名字1,...,名字n}: 枚举类型名字通常并不真的使用,要用的是大括号里面的名字,因为 ...
- 网易之小易最近在数学课上学习到了集合的概念,集合有三个特征:1.确定性 2.互异性 3.无序性.需要根据给定的w,x,y,z,求出集合中一共有多少个元素。
import java.util.HashSet; import java.util.Scanner; import java.util.Set;/*** 小易最近在数学课上学习到了集合的概念,集合有 ...
- 【网易笔试】小易最近在数学课上学习到了集合的概念
/***************************************************** 小易最近在数学课上学习到了集合的概念,集合有三个特征:1.确定性 2.互异性 3.无序性. ...
- MongoDB学习笔记~对集合属性的操作
$unset清除元素 请注意在单个数组元素上使用$unset的结果可能与你设想的不一样.其结果只是将元素的值设置为null,而非删除整个元素.要想彻底删除某个数组元素,可以用$pull 和$pop操作 ...
- java枚举类型及枚举集合
文章目录 一.枚举类型 二.switch 操作 三.自定义枚举类 四.相关枚举类 4.1 EnumMap 枚举型映射/字典 4.2 EnumSet 枚举集合 一.枚举类型 /*** @author z ...
最新文章
- 编程笔试(解析及代码实现):求出一个整数中各位数上所包含全部质数之和
- 学习机器学习的项目_辅助项目在机器学习中的重要性
- Python--day60--一个简单(不完整)的web框架
- [vue] 跟keep-alive有关的生命周期是哪些?描述下这些生命周期
- Hostiko v54.0 – WordPress WHMCS-云服务器VPS主机销售模板源码
- mysql sign_mysql - 随笔分类 - signheart - 博客园
- python 实现大文件md5值计算
- window两个窗口上下摆放_滑动窗口技巧
- 华为harmonyOS开发者日,华为首届HarmonyOS开发者创新大赛收官
- c语言打印字符数据在屏幕上,在屏幕上输出各种类型的数据
- INCONEL 600该合金因其强度和耐腐蚀性而广泛用于化学工业
- TrinityCore3.3.5环境搭建
- android是什么意思
- android 面包屑控件,android面包屑導航欄的實現
- 游戏服务器是干什么的(大话、浅析)
- 【Unity2D入门教程】简单制作一个弹珠游戏之制作场景①(开场,结束,板子,球)
- Keyshot渲染-关于导入提示:未检索到几何图形的解决方法。
- python输出字体的大小_Python之美——一只数据狗的笔记[长期更新]
- Vue组件自调用/无限递归导航/element-ui导航封装
- dreamweaver网页设计作业制作 学生NBA篮球网页 WEB静态网页作业模板 大学生校园篮球网页代码 dw个人网页作业成品
热门文章
- 常见的信息收集工具和手段
- orangepi pc GPIO 管脚图
- 两个图片叠加在一起css,css实现图片叠加的几种思路(记录笔记)
- Java中的正则表达式 regex
- 访问不到webapp
- 加速器,陀螺仪测量移动距离的方法
- android studio 添加图片进入mipmap文件包
- 《数据结构》邓俊辉 网课习题详细解析(第五章:二叉树)
- 如何修改vant组件中filed的placeholder的 颜色
- Python里面的编码问题真的让人快疯了.. Python乱码 b'\x1f\x8b\x08\x00\x00\x00\x00\x00\...'