我目前阅读Rust代码的一个不适应点就是Rust中的模式匹配match语法, 以及两个语法糖if let
和while let
,为了强化自己的记忆,于是便有了第三课。
所谓的模式匹配,就是对于不同情况采取不同的处理方法,
让我们想象一个应用场景,将一段DNA序列进行互补,即A->T, T->A, C->G, G->。
对于Python而言,我们可以通过字典(dict)进行翻译
1 2 3 4 5 6 7
| dna = "ATCG" trans_dict = {'A' : 'T', 'T': 'A', 'C':'G', 'G':'C'} translated = "" for base in dna: translated+=(trans_dict[base])
print(translated)
|
如果是C语言的话,我会用switch语法,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <stdio.h> #include <stdlib.h> #include <string.h>
int main(){ char *dna = "ATCG"; int dna_len = strlen(dna); char *translated = (char*)malloc( sizeof(char) * dna_len);
for (int i = 0; i < dna_len; i++){ char base = dna[i]; switch (base) { case 'A': translated[i] = 'T'; break; case 'T': translated[i] = 'A'; break; case 'C': translated[i] = 'G'; break; case 'G': translated[i] = 'C'; break; default: translated[i] = 'N'; break; } } printf("%s\n", translated); return 0; }
|
Rust提供了match用于模式匹配。以一个碱基为例,我们输入’A’, 希望翻译成’T’, 下面是非常粗糙的代码
1 2 3 4 5 6 7 8 9 10
| fn main(){ let base = 'A'; let trans = match base { 'A' => 'T', 'T' => 'A', 'C' => 'G', 'G' => 'C', _ => 'N', }; println!("{}", trans);
|
其中match语法描述如下
1 2 3 4 5 6
| match 变量名 { 匹配类型1 => 代码1, 匹配类型2 => 代码2, .... _ => 其他 }
|
match要求我们考虑所有的情况, 而一个utf-8字符肯定不只是ATCG这四个,因此其他情况需要用_
指代,否则会报错。
对于一段序列, 我们可以写一个循环,直接在里面嵌套一个match语法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| fn main(){ let dna = "ATCG".to_string(); let mut translated = String::new();
for i in dna.chars() { translated.push( match i { 'A' => 'T', 'T' => 'A', 'C' => 'G', 'G' => 'C', _ => 'N', } ) } println!("{}", translated );
}
|
或者考虑将match匹配的部分封装到一个函数中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| fn translate(base: char ) -> char {
match base { 'A' => 'T', 'T' => 'A', 'C' => 'G', 'G' => 'C', _ => 'N', } }
fn main(){
let dna = "ATCG".to_string(); let mut translated = String::new();
for base in dna.chars() { translated.push(translate(base));
} println!("{}", translated ); }
|
但是match不仅