Day2我們可以看到將字串轉成疊代器(Iterator)後使用了collect()
轉成Vec<char>
,最後回傳時又將chars.into_iter().collect()
}轉成String
。
impl Solution {
pub fn reverse_vowels(s: String) -> String {
let mut chars: Vec<char> = s.chars().collect();
let (mut l, mut r) = (0, chars.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,
}
}
為何collect()
可以回傳Vec<T>
也可以是String,
我們可以從下圖看到collect()
後,都可以轉換成有實作FromIterator的型別,且Rust 會從上下文推斷型別,因為有回傳型別且FromIterator<char>
內建可以轉成String於是自動轉成String
,但若不夠清楚無法從上下文推斷型別,需要宣告型別否則系統會報錯,請你定義要轉的型別。
來源:https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect
impl FromIterator<char> for String
來源:https://doc.rust-lang.org/std/iter/trait.FromIterator.html#impl-FromIterator%3Cchar%3E-for-String
Rust 中每個值在同一時間只能有一個擁有者。
在編譯時有固定大小、存在stack上的值(i32,bool,f64)在移動(move)時是直接複製一個值給新的變數
而存在heap上的值移動(move)給另一個變數或函式時,會把所有權交出去,原本的變數就失效了,除非使用clone()
複製一份另外存。
let x = 10; // i32 是 Copy
let y = x; // 複製一份
println!("x = {}, y = {}", x, y); // ✅ x 還能用
let s1 = String::from("hi");
let s2 = s1; // move
// println!("{}", s1); // ❌ s1 已無效
println!("{}", s2);
編譯時需要滿足
同時允許多個不可變借用 &T
let mut x = 10;
let r1 = &x;
let r2 = &x; // 多個共享引用 OK
// let m = &mut x; // ❌ 有共享引用存活時,不能再拿可變引用
println!("{}, {}", r1, r2);
最多只能有一個可變借用 &mut T
let mut x = 10;
let m = &mut x; // 拿了獨佔引用
*m += 1;
// let r = &x; // ❌ 獨佔引用存活時,不可再拿共享引用
println!("{}", m);
1和2不能同時存在。
借用必須不懸空
let r: &i32;
{
let x = 42;
r = &x; // ❌ x 只在內層活著
}
// println!("{}", r); // r 指向已被釋放的 x
所以在這裡Leetcode 345. 中宣告左右指標let (mut l, mut r) = (0, chars.len()-1)
或是is_vowel(c: char)
都是複製值沒有移動所有權。
最後講解回傳的chars.into_iter().collect()
,來講解Vec<T>
轉成迭代器的方法
into_iter()
拿到值所有權
iter()
不可變借用只能讀不能改
iter_mut()
可變借用能讀能改
語法 | 方法 | 拿到的元素型別 | 說明 |
---|---|---|---|
for x in chars |
into_iter() |
i32 |
x取得所有權,chars 失去所有權 |
for x in &chars |
iter() |
&i32 |
取得不可變借用 |
for x in &mut chars |
iter_mut() |
&mut i32 |
取得可變借用 |
fn main() {
let chars = vec!['a', 'b', 'c'];
for x in chars.into_iter() {
println!("{}",x);
}
//println!("{}",chars); // ❌chars 失去所有權
}
//a
//b
//c
fn main() {
let chars = vec!['a', 'b', 'c'];
for x in chars.iter() {
println!("{}",x);
}
println!("{:?}",chars);
}
//印出
//a
//b
//c
//['a', 'b', 'c']
fn main() {
let mut chars = vec!['a', 'b', 'c'];
for x in chars.iter_mut() {
if *x=='a' {
*x='A';
}
}
println!("{:?}",chars);
}
//['A', 'b', 'c']
&T
或最多只能有一個可變借用 &mut T
for x in chars
會把所有權移動到x