iT邦幫忙

2025 iThome 鐵人賽

DAY 2
0
Rust

用刷題來練RUST系列 第 2

用刷題來練RUST Day 2 疊代器Iterator & Match & 巨集Marco

  • 分享至 

  • xImage
  •  

Day 1提到的解法中使用了chars() ,這方法回傳為實作疊代器(Iterator)的型別Chars<’a>,疊代器(Iterator)呼叫.next()會依序取得char型別的值,直到最後回傳None,因為會改變疊代器內部紀錄序列位置的狀態,Rust預設是不可變宣告,所以宣告疊代器變數時要宣告成可變 mut

impl Solution {
    pub fn merge_alternately(word1: String, word2: String) -> String {
        let mut new = String::new();
        let mut iter1 = word1.chars();
        let mut iter2 = word2.chars();

        loop {
            match (iter1.next(), iter2.next()) {
                (Some(c1), Some(c2)) => {
                    new.push(c1);
                    new.push(c2);
                }
                (Some(c1), None) => {
                    new.push(c1);
                    new.extend(iter1);
                    break;
                }
                (None, Some(c2)) => {
                    new.push(c2);
                    new.extend(iter2);
                    break;
                }
                (None, None) => break,
            }
        }
        new
    }
}

https://ithelp.ithome.com.tw/upload/images/20250914/20142205br1W2iaU83.png
來源:https://doc.rust-lang.org/std/primitive.str.html#method.chars

Option

在範例程式中,我們看到Rust中疊代器是回傳Some<T>None,因為Rust中沒有空值(Null),要表達空值的概念是用一個列舉Option<T>來實現,有了這概念,編譯器在看到Option<T>時才會處理數值是否為空的條件。

enum Option<T> {
    None,
    Some(T),
}

Match

我們可以透過Match組成一系列的模式並依匹配到的模式

來控制流程,如1768. Merge Strings Alternately,我們組成四種模式,並定義每個模式要走的流程,最後回傳新字串。

  1. 疊代器1、2有值,依序把回傳字元加到新字串

  2. 疊代器1有值,疊代器2用完了,用extend()把剩下的所有元素加到新字串

  3. 疊代器1用完了,疊代器2有值,用extend()把剩下的所有元素加到新字串

  4. 都沒值,什麼都不做。

match (iter1.next(), iter2.next()) {
                (Some(c1), Some(c2)) => {
                    new.push(c1);
                    new.push(c2);
                }
                (Some(c1), None) => {
                    new.push(c1);
                    new.extend(iter1);
                    break;
                }
                (None, Some(c2)) => {
                    new.push(c2);
                    new.extend(iter2);
                    break;
                }
                (None, None) => break,
            }

今天我們要匹配的許多值來控制流程,可以先match目標值給狀態,再依狀態來控制流程,來刷個一題練習一下。

Leetcode 345. Reverse Vowels of a String

題目:將字串母音做相對位置交換,IceCreAm變成AceCreIm,leetcode變成leotcede

輸入:"IceCreAm"

輸出:"AceCreIm"

限制:

  1. 1≤字串長度≤3*10^5

  2. 字元都是ASCII能表達的

做法:先用.chars().collect()將String轉成Vec<char>、雙指針紀錄開始和結束的位置,判斷每個字元是否為母音,不是就移動一格,(false,_)意思是只看第一個值,忽略第二個值不管,等找到兩個母音(true,true)時做交換。

impl Solution {
    pub fn reverse_vowels(s: String) -> String {
        let mut chars: Vec<char> = s.chars().collect();
        let (mut l, mut r) = (0, s.len()-1);

        while l < r {
            match (is_vowel(chars[l]), is_vowel(chars[r])) {
                (false, _) => l += 1,
                (_, false) => r -= 1,
                (true, true) => {
                    chars.swap(l, r);
                    l += 1;
                    r -= 1;
                }
            }
        }

        chars.into_iter().collect()
    }
}

fn is_vowel(c: char) -> bool {
    match c {
        'a' | 'e' | 'i' | 'o' | 'u'
        | 'A' | 'E' | 'I' | 'O' | 'U' => true,
        _ => false,
    }
}

巨集

巨集可以想成Rust中的按鍵精靈,Rust幫你把指令寫好,在編譯期間幫你生成程式碼,省下手動寫的重複邏輯,為了可讀性我們寫了一個function is_vowel做母音判斷並回傳布林值,可以用巨集matches!(val, pattern1 | pattern2),將符合pattern的回傳true。

fn is_vowel(c: char) -> bool {
    match c {
        'a' | 'e' | 'i' | 'o' | 'u'
        | 'A' | 'E' | 'I' | 'O' | 'U' => true,
        _ => false,
    }
}
//
fn is_vowel(c: char) -> bool {
    matches!(
        c,
        'a' | 'e' | 'i' | 'o' | 'u' |
        'A' | 'E' | 'I' | 'O' | 'U'
    )
}

上述matches!可能看不出來可以省多少工,我們來看如何用巨集宣告Vec<i32>

//沒使用巨集
let v = {
    let mut temp = Vec::new();
    temp.push(1);
    temp.push(2);
    temp.push(3);
    temp.push(4);
    temp.push(5);
    temp
};
//使用巨集
let v = vec![1, 2, 3, 4, 5];

Day2總結

  1. 疊代器(Iterator)與 next()方法拿下一個值
  2. Rust中沒有空值(Null)會用Option<T>判斷有沒有值
  3. match控制流程
  4. 巨集

參考資料

  1. https://doc.rust-lang.org/std/primitive.str.html#method.chars
  2. https://rust-lang.tw/book-tw/ch06-02-match.html
  3. https://rust-lang.tw/book-tw/ch18-01-all-the-places-for-patterns.html

上一篇
用刷題來練RUST Day 1 前言 & 字串 String
下一篇
用刷題來練RUST Day 3 collect & 所有權 ownership & 借用檢查 borrow check
系列文
用刷題來練RUST8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言