隱私權政策

搜尋此網誌

技術提供:Blogger.

關於我自己

我的相片
目前從事軟體相關行業,喜歡閱讀、健身、喝調酒。習慣把遇到的問題記下來,每天做一些整理方便自己以後查。 Python、Rust、Kotlin等程式語言皆為自學,目前比較著重在Rust語言,歡迎一起討論。

2024年1月23日 星期二

【生活】拔智齒記


拔牙前

  前一陣子牙齒痛,長了一顆智齒,根據第一家醫生的說法是水平的,在很裡面還往嘴巴裡面斜進去。那時候聽起來就很不妙,因為有聽說在比較裡面的智齒會有神經的問題。後來上網查有一家感覺拔智齒還可以的診所,有在預約過去看一次。

  但這次第二家醫生檢查完看起來很猶豫,他說這種的他怕拔起來會有驚喜,怕下面倒鉤很深。後來醫生跑去問他的學長,問說這個可不可以拔,他們討論一陣子後說可以拔。诶不是聽起來就超詭異,不敢拔就不要拔讓我轉診不好嗎,這種比較深的智齒被這樣講我怎麼敢給他拔。後來我稍微問一下拔這種智齒要多久,醫生說大約四十分鐘。聽完還是只能說先考慮看看。

  後來朋友有介紹幾家有名的,但都需要轉診單,之前去診所沒想到要拿轉診單。於是又跑去找第三家診所,為了拿轉診單去的。這次這家醫生也不囉嗦,直接說這個他不敢拔可以幫我轉診。醫生開轉診單到郭儒全診所,號稱台北拔智齒名醫,但評價超兩極,有人說態度超差有人說根本神醫一下就拔完。我朋友直的智齒去那邊拔不到十分鐘,於是抱持著玻璃心碎掉的心情到時候去這家拔。不過此時已經到當兵前三天了,於是乎想說當完兵再去拔,並且請朋友幫我預約當完兵後的時段。

  有趣的來了,我原本希望星期五拔,這家診所要求前一週預約。我朋友抱持著試試的心態前一週星期四打電話去,直接被罵說前一週才可以。於是隔天朋友又再打一次,不知道為何每一通都沒人接,上網查發現阿幹怎麼永久歇業了。在軍中牙齒痛聽到這個消息真得哭笑不得,原本還抱持著有人惡作劇把他用永久歇業,跑去問一些人才發現他居然退休了,我就差一天欸......。

  跑回去第三間診所問,這個郭儒全倒了我該怎麼辦。醫生還說:「郭儒全?郭儒全倒了?他怎麼會沒有通知我。」後來他又推薦我另一間立新醫院的陳院長,可以去給他看看。這家比較好預約,上網預約隔天就會有人打電話來確認,而且可以預約比較久以後的時間。

拔牙當天

  這已經是我第四間診所了,這次終於如願以償把智齒拔掉。那時候預約7:15,我大約7:10到,到了之後先拍X光,大約7:30就叫我躺在看診區的椅子上。7:45醫生幫我打麻醉,很多人都跟我說打麻醉很痛要有心理準備,不過我自己的感覺是還好,平常嘴破比較痛。打完麻醉醫生就不見了,後來聽到隔壁隔壁有一些牙醫器具的聲音,猜測他應該就是幫我打完麻醉就先去幫別人拔牙之類的,根本無情的拔牙機器。8:00的時候輪到我了,先遮住我的眼睛,然後醫生說「要開始拔囉,因為拔牙會有一些拉扯感要撐住喔」,後來感受到他手伸進來在扯,雖然有打麻醉但還是有一點點點點點痛。當他伸進嘴巴扯兩次,有第三次心理準備後,醫生就說咬住,棉花咬緊,至後就叫我去拿藥了。What the hell,此時才8:00剛跳到8:01,他拔一個其他醫生要三四十分鐘的水平智齒只要不到一分鐘?牙齒還沒看到他就叫我出去了,真的靠北快。

  之後就是去一樓櫃台拿一些單子,順便問說有沒有要回診拆線。櫃台說,你下次來就是準備拔其他顆,你沒有線不用拆。後來才想起來他拔我的水平智齒沒有切肉也沒有縫線,真的是拔出來而已。去對面藥局拿完藥後,就搭uber回家,此時大約8:30,嘴巴有一點點怪怪的感覺,也不太痛。到家大約9:00,快速洗個澡,換紗布順便吃藥,麻藥可能已經慢慢退了有一點痛的感覺,但說真的不太會痛。怕隔天臉會整個腫起來還是有乖乖冰敷,不過事後想好像完全沒差。

拔牙之後

  晚上其實睡不太好,並不是說會痛,而是一直有個麻麻腫腫的感覺。早上起來後嚇到,傷口幾乎不會痛,臉也完全沒腫起來。最好笑是早上起來給家人看,家人指著我沒拔智齒的那邊臉頰說臉腫腫的。一臉問號???

  雖然感覺不太會痛,但隔天還是只吃流質食物,布丁、稀飯之類的。再隔一天星期五就乖乖去公司上班,早餐午餐都是吃麵包,同事看到我還很訝異,以為我會腫起來然後完全不能吃東西。晚餐吃丸龜的冷面,有嘗試吃魚肉。星期六就正常吃飯了,不要咬太硬的肉基本上都沒事。星期六晚上還有吐兩大口血塊和吞下好幾個小口的血塊。雖然醫生說要吞下去不要吐出來,但大塊的真的太誇張了,完全不敢吞,小塊的就還好。

小小心得

  這次拔智齒原本做了很多心理準備,但實際上拔的時候比想像輕鬆很多,真心推薦可以去這間診所看看。不過不要為了洗牙之類的去,院長真的很忙,看他得手都沒停過。如果找他是為了洗牙補牙看Google評論都挺不好的。


最後醫生有說還有兩顆要拔,經過這次經驗,我只能說,他開始痛我在拔^^


立新口腔顎面外科牙醫診所
地址:臺北市萬華區西園路2段233號

--

智齒的智是智障的智

2024年1月22日 星期一

Rust read_dir概述 - 對路徑內所有文件檢查


read_dir概述

read_dir被分賴在fs裡面

主要判斷路徑內有哪些文件

並且以此為基礎去操作


文件這樣解釋

read_dir[1]

pub fn read_dir<P: AsRef<Path>>(path: P) -> Result<ReadDir>

輸入一個路徑

回傳Result,Result包著一個迭代器ReadDir[2]

迭代器內部則是Result<DirEntry, error>

也就是出現兩層Result

解釋起來有點饒口

舉個例子大概長這樣

use std::fs;

fn main() {
    let dir_path = "src";
    if let Ok(entries) = fs::read_dir(dir_path) {
        for entry in entries {
            let entry_ = entry.unwrap();
            println!("{:?}", entry.path());
        }
    }
}
"src\\build.rs" "src\\handler.rs" "src\\lib.rs" "src\\main.rs"

設定路徑dir_path

使用read_dir將路徑內的文件資料放入entries迭代器中

透過for entry迭代entries裡面的東西

再把entry unwrap可以得到DirEntry[3],放入entry_裡面

此時就可以對這個文件操作

例如我想要獲得這個路徑

就是直接.path()輸出就好


DirEntry[3]

pub struct DirEntry(/* private fields */);

DirEntry為ReadDir迭代器中的元素結構

可以檢查文件的屬性

常見的例如

path[4]

pub fn path(&self) -> PathBuf

path為獲得文件路徑


file_name[5]

pub fn file_name(&self) -> OsString

file_name可以獲得檔案的名稱

fn main() {
    let dir_path = "src";
    if let Ok(entries) = fs::read_dir(dir_path) {
        for entry in entries {
            let entry = entry.unwrap();
            println!("{:?}", entry.file_name());
        }
    }
}
"build.rs" "handler.rs" "lib.rs" "main.rs"


metadata[6]

pub fn metadata(&self) -> Result<Metadata>

metadata可以知道資料的資訊

例如可以知道是否為檔案、是否為資料夾、最後修改時間等等

use std::fs;

fn main() {
    let dir_path = "src";
    if let Ok(entries) = fs::read_dir(dir_path) {
        for entry in entries {
            let entry = entry.unwrap();
            let metadata = entry.metadata().unwrap();
            println!("is dir: {:?},  last modified: {:?}",
                metadata.is_dir(), metadata.modified());
        }
    }
}
is dir: false, last modified: Ok(SystemTime { intervals: 133504035161114808 }) is dir: false, last modified: Ok(SystemTime { intervals: 133504035348568046 }) is dir: false, last modified: Ok(SystemTime { intervals: 133504035212331473 }) is dir: false, last modified: Ok(SystemTime { intervals: 133504051360968232 })


參考資料

[1] https://doc.rust-lang.org/std/fs/fn.read_dir.html

[2] https://doc.rust-lang.org/std/fs/struct.ReadDir.html

[3] https://doc.rust-lang.org/std/fs/struct.DirEntry.html

[4] https://doc.rust-lang.org/std/fs/struct.DirEntry.html#method.path

[5] https://doc.rust-lang.org/std/fs/struct.DirEntry.html#method.file_name

[6] https://doc.rust-lang.org/std/fs/struct.DirEntry.html#method.metadata

2024年1月18日 星期四

Rust 迭代skip_while - 有條件的略過某些元素


迭代skip_while

skip_while跟skip[1]有一點點不一樣

skip是直接跳過前幾個元素

而skip_while則是可以設定條件

並根據條件跳過前幾個元素


文件這樣解釋

skip_while[2]

fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
where
    Self: Sized,
    P: FnMut(&Self::Item) -> bool,

self是迭代器本身

輸入一個閉包

當達成閉包條件的時候會跳過這個元素

最後輸出一個迭代器

但要注意,如果有一個元素是false

則skip_while的工作就結束了

之後就不會跳過


舉個例子

假設我有一個數組

想要把前面小於3的元素都去除

可以這樣做

fn main() {
    let data = vec![1, 2, 3, 4, 5, 2, 7, 8, 9, 10];
    let res = data.into_iter().skip_while(|x| x < &3).collect::<Vec<_>>();
    println!("{:?}", res);
}
[3, 4, 5, 2, 7, 8, 9, 10]

先把data丟入迭代器中

使用skip_while,閉包條件設置小於3

這樣就可以把小於3的數字都去除

直到第一個出現大於等於3的

skip_while的工作就結束了

因此5後面還有一個2

他不會被去除


實際例子

假設我有一堆網址長這樣

    let link = vec![
        "1. https://www.google.com/",
        "2. https://www.facebook.com/",
        "3. https://www.youtube.com/?gl=TW&hl=zh-TW",
        "4. https://www.dcard.tw/",
        "5. https://shopee.tw/",
    ];

但我不想要編號本身

我希望從網址https開始

因此可以這樣做

fn main() {
    let link = vec![
        "1. https://www.google.com/",
        "2. https://www.facebook.com/",
        "3. https://www.youtube.com/?gl=TW&hl=zh-TW",
        "4. https://www.dcard.tw/",
        "5. https://shopee.tw/",
    ];

    let res: Vec<String> = link
        .into_iter()
        .map(|x| x.chars().skip_while(|c| !c.is_alphabetic()).collect())
        .collect::<Vec<_>>();
    println!("{:?}", res);
}
["https://www.google.com/",
"https://www.facebook.com/",
"https://www.youtube.com/?gl=TW&hl=zh-TW",
"https://www.dcard.tw/", "https://shopee.tw/"]

先將網址數組丟入迭代器中

map[3]取出每個網址

並且判斷每個網址的字元char

再使用skip_while並以is_alphabetic[4]判斷是否為字母

當為字母實則結束skip

最後輸出


參考資料

[1] https://lageeblog.blogspot.com/2024/01/rust-skip.html

[2] https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.skip_while

[3] https://lageeblog.blogspot.com/2023/10/rust-map.html

[4] https://lageeblog.blogspot.com/2024/01/rust-isalphabeticisalphanumeric.html

2024年1月17日 星期三

Rust 迭代 skip - 跳過迭代器前幾個元素


迭代skip

有時候迭代器想要跳過前幾個元素

例如說網頁、路徑等等

可能某些情況下前幾個並不是想要的

這時候就可以用skip跳過


文件這樣解釋

skip[1]

fn skip(self, n: usize) -> Skip<Self>
where
    Self: Sized,

自身為迭代器

可以輸入一個數字,此數字表示前幾個元素捨棄

最後輸出一個迭代器


例子

fn main() {
    let data = [1, 2, 3];
    let res = data.iter().skip(2).collect::<Vec<_>>();
    println!("Result: {:?}", res);
}
Result: [3]

假設有個data是1 2 3

放入迭代器

去除掉前兩個

就只會剩下3


實際應用

我最常是用在看資料夾內所有東西上

因為有些做法會連資料夾本身也算進去

而不是只會顯示資料夾裡面的東西

例如

use walkdir::WalkDir;

fn main() {
    // 指定要遍歷的資料夾路徑
    let folder_path = "src";

    // 使用 WalkDir 遍歷資料夾
    for entry in WalkDir::new(folder_path) {
        if let Ok(entry) = entry {
            let path = entry.path();
            println!("Full Path: {:?}", path);
        }
    }
}
Full Path: "src" Full Path: "src\\main.rs"

使用WalkDir[2]遍歷資料夾內的東西

但如果只是這樣打

可以看到輸出結果為src和src\main.rs

連資料夾本身也算進去了

這可能不是我想要的結果

因此可以使用skip跳過資料夾本身

use walkdir::WalkDir;

fn main() {
    // 指定要遍歷的資料夾路徑
    let folder_path = "src";

    // 使用 WalkDir 遞迴地遍歷資料夾
    for entry in WalkDir::new(folder_path).into_iter().skip(1) {
        if let Ok(entry) = entry {
            let path = entry.path();
            println!("Full Path: {:?}", path);
        }
    }
}
Full Path: "src\\main.rs"

迭代的時候跳過第一個資料夾

從資料夾內部開始輸出


參考資料

[1] https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.skip

[2] https://docs.rs/walkdir/latest/walkdir/

2024年1月16日 星期二

Rust 字元is_alphabetic、is_alphanumeric概述 - 判斷是否為字母


字母判斷

判斷字元是否為字母有幾個方法

分別是is_alphabetic和is_alphanumeric

差別在於一個是單純判斷字母

另一個是可以額外判斷樹字


文件這樣解釋

is_alphabetic[1]

pub fn is_alphabetic(self) -> bool

is_alphabetic可以判斷字母


舉個例子

fn main() {
    let c_lowercase = 'a';
    let c_uppercase = 'Z';
    let c_digit = '5';
    let c_punctuation = '!';
   
    println!("Is alphabetic (lowercase): {}", c_lowercase.is_alphabetic());  
    println!("Is alphabetic (uppercase): {}", c_uppercase.is_alphabetic());  
    println!("Is alphabetic (digit): {}", c_digit.is_alphabetic());          
    println!("Is alphabetic (punctuation): {}", c_punctuation.is_alphabetic());    
}
Is alphabetic (lowercase): true Is alphabetic (uppercase): true Is alphabetic (digit): false Is alphabetic (punctuation): false

其中a和Z都是字母

因此輸出為true

但5和!不是

輸出false


is_alphanumeric[2]

pub fn is_alphanumeric(self) -> bool

is_alphanumeric可以判斷字母加上數字

也就是is_alphabetic和is_numeric[3]加起來


舉個例子

fn main() {
    let c_lowercase = 'a';
    let c_digit = '5';
    let c_punctuation = '!';
   
    println!("Is alphanumeric (lowercase): {}", c_lowercase.is_alphanumeric());
    println!("Is alphanumeric (digit): {}", c_digit.is_alphanumeric());
    println!("Is alphanumeric (punctuation): {}", c_punctuation.is_alphanumeric());
}
Is alphanumeric (lowercase): true Is alphanumeric (digit): true Is alphanumeric (punctuation): false

除了字母a會是true

數字5也會是true

驚嘆號則不是


其他語言

fn main() {
    let chinese = '校';
    let emoji = '💝';
   
    println!("Is alphanumeric (校): {}", chinese.is_alphabetic());
    println!("Is alphanumeric (校): {}", chinese.is_alphanumeric());
    println!("Is alphanumeric (💝): {}", emoji.is_alphabetic());
    println!("Is alphanumeric (💝): {}", emoji.is_alphanumeric());
}
Is alphanumeric (校): true Is alphanumeric (校): true Is alphanumeric (💝): false Is alphanumeric (💝): false

中文字也算是字母的一種

因此也會顯示true

但emoji不是


參考資料

[1] https://doc.rust-lang.org/std/primitive.char.html#method.is_alphabetic

[2] https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric

[3] https://doc.rust-lang.org/std/primitive.char.html#method.is_numeric

2024年1月14日 星期日

Rust - 迭代all, any, filter, find差別


迭代all, any, filter, find

我覺得迭代裡面有四個很像

all[1], any[2], filter[3], find[4]

差別的地方有幾個

all和any輸出是bool,為true或false

filter會輸出一個迭代器

find輸出一個元素


例子

假設我有一組數組

閉包條件都是判斷是否為偶數

結果會長這樣

fn main() {
    let data = vec![2, 4, 6, 8, 10, 11, 12, 14, 16, 18, 20];
    let all_res = data.iter().all(|x| x % 2 == 0);
    let any_res = data.iter().any(|x| x % 2 == 0);
    let filter_res = data.iter().filter(|x| *x % 2 == 0).collect::<Vec<_>>();
    let find_res = data.iter().find(|x| *x % 2 == 0).unwrap();
    println!("all: {}", all_res);
    println!("any: {}", any_res);
    println!("filter: {:?}", filter_res);
    println!("find: {}", find_res);
}
all: false any: true filter: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] find: 2

all會判斷是否數組內所有元素都滿足條件,因為數組有奇數所以不符合

any會判斷是否數組內至少一個元素滿足條件,只要一個就會true

filter會將所有數組內滿足條件的輸出,因此除了奇數以外都會輸出

find則是會輸出第一個滿足條件的元素,也就是2


參考資料

[1] https://lageeblog.blogspot.com/2024/01/rust-all.html

[2] https://lageeblog.blogspot.com/2024/01/rust-any.html

[3] https://lageeblog.blogspot.com/2023/10/rust-filter.html

[4] https://lageeblog.blogspot.com/2023/10/rust-find.html









2024年1月13日 星期六

【讀後心得】厚黑學 - 所謂的英雄偉人,不過是臉厚心黑而已


厚黑學 - 所謂的英雄偉人,不過是臉厚心黑而已

  最近讀了李宗吾的厚黑學,但這本是白話的版本,也不確定原版長怎樣。書中一開始就有提到,我們所提到的偉人,不過是臉皮厚、心地黑而已。劉備會成功,因為他臉皮厚;曹操會成功,因為他心地黑。臉皮厚心地黑不管在什麼時候都用得到,再不然乞討的時候也可以多乞討一點。我覺得讀這本書並不是要教你臉皮要多厚心要多黑,而是其他人用厚黑的方式對待你的時候要有辦法知道並且應對。可怕的地方在於,看這本書的時候總會覺得在很多地方都會有類似的影子,彷彿真的成功的人都是這樣做,例如有求官做官箴言、做事方法

求官六字箴言

  1. 空:一心一意求官
  2. 貢:有孔必鑽,無孔也要想辦法鑽
  3. 沖:吹牛
  4. 捧:捧場諂媚
  5. 恐:恐嚇
  6. 送:送禮

  會發現這六個不管在職場、在政治上都很常看到。選舉時一心一意求官(空),想盡辦法當官(貢),政見不用說很多根本亂提(沖),看到選民說一些諂媚鬼話(捧),快到選舉時突然恐嚇不投他可能會發生什麼事(恐),給予一些里民旅遊、里民聚餐等等(送)。

做官六字箴言

  1. 空:空洞模糊,不管在文字上還是辦事上,總有辦法可以抽身走人
  2. 恭:諂媚上司和其親朋好友
  3. 繃:儀表上相是赫赫有名的大人物,滿腹經綸的樣子
  4. 兇:要夠兇悍,但要裹上一層仁義道德
  5. 聾:裝聾,不需要多在意別人講的話
  6. 弄:錢,有些事花多點錢都該讓他過
  當時看到做官箴言,心理大受震撼,哇這不就是政治上的現狀嗎。講話都不知道在講什麼(空),去巴在某個勢力上(恭),每天穿著西裝講得好像很有道理的話(繃),有時候無法控制情緒很兇但事後可以用一個歪理圓回來(兇),人民講話一堆事聽不到(聾),蓋捷運(弄)。這六個字真的完全就是現況。

做事方法

鋸箭法

  現在很多行政單位都是用這個方法。假設有個人中箭,我把外面的箭桿幫你鋸掉。那剩下在身體裡面的箭怎麼辦?你去找別人吧~一個合格的踢皮球選手絕對不會多幫你做事。最屌的就是很多人會裹上仁義道德,說「我也很想幫你,但可惜我沒有權限」之類的屁話,但其實很多時候這明明也是他的工作範圍。

補鍋法

  補鍋法更猛,猛在他偷偷的把事情搞得更麻煩,你卻還會更感謝他。有人補鍋的師傅去你家看到你的破洞的鍋子,趁你不注意把他敲出裂痕,等你回來後跟你說你看還好有來檢查,不然這個裂痕你沒看到。先將你的東西破壞過後才又給予恩惠。

用法

  常有人說,商家通常不對內行人發貨,因為商家不法對內行人使用厚黑學,會馬上被看出來。不管做任何事都應該設想所有情況,其他人攻過來時才可以應對。讀這本書目的也是如此,要知道別人正在使用厚黑以此反擊。但千萬不要學了一點點就急著使用,不知兵而用兵,將兵敗亡國,厚黑也是。在使用厚黑時應在表面上裹一層仁義道德。當因私利而使用厚黑時,必定人人唾棄,但如果是因為公眾利益而使用,反而是至高無上的道德。厚黑有三個境界

  1. 厚如城牆,黑如煤炭
  2. 厚而硬,黑而亮
  3. 厚而無形,黑而無色

1.就是已經略懂厚黑學,但還是會被大砲擊穿。2.則是融會貫通,已經知道怎麼扛別人的大砲。3.則是厚黑最高境界,看不出來你正在使用厚黑。

  厚黑學是一個只能讀不能說的一件事,當你明確的對別人說正在使用厚黑畢竟會遭到責罵。因此要將其埋藏在心中,並且當聊天時也不要把厚黑講出來,要順著對方的話講。如果對方是讀儒道的,那就跟他們講儒道;讀聖經就講聖經。如同政治一樣,當立場不同切記不要強迫改變別人立場,特別是自己的立場在整個社會是逆風的情況,也就是俗稱見人說人話、見鬼說鬼話。


心得

  李宗吾說,世界上有三本書,一本是宇宙真理的書,一本是腦中的書,一本則是古今人所著的書。每個人都應該要做為一個獨立思考的人,要懷疑世上所有的書。不要總以古人審判自己,要拿自己的思想去跟古人對照。西方提出一個學說時總是可以被懷疑,而中華思想卻用威脅的方式,例如關聖帝君說過「不信吾教,請試吾刀」。那就不好意思了,這本書確實是有一些看起來很奇怪的地方。

  有時候真的不能理解書想表達什麼,很喜歡用數學式子表示心理學,但對我來說,數學式子應該是死的,對就是對,錯就是錯。但心理學是模糊的,會有很多模稜兩可的空間,沒有絕對的答案,因此解析別人心裡才會顯得有趣。而此書的最後大約一百頁,全部都在介紹孔孟以及老子思想,而且重複的話一而再再而三的講,看到最後甚至忘記這本書叫做厚黑學,還以為在讀儒家或道家的書。書中有提到李宗吾並不喜歡把一本書完整的看完,很好奇是不是這個緣故,書中提到的古云才都只有那幾句話。

  李宗吾對中華文化有個莫名的信心,非常看不慣西方強國。總覺得應該把所有弱小的國家統整起來,直接對西方強權開戰,這樣就可以贏,並且認為應該是中國當作領導者。而文化也應該要統一,中華文化上千年歷史,應該和西方文化、印度文化統一,並且以中華文化為主,大家都應該讀中華文化。有時候真的覺得很厲害,怎麼可以這麼有自信,但實際上就是現在的科學就是當初西方文化所發現的。

推薦

★★★☆☆

  看前面在講述厚黑學的時候很震撼,李宗吾對自己提出的學問有極度的自信,並且在此基礎上若有人懷疑他,有理的話他就改,無理的話也不會爭論。這種自信且能屈能伸的態度令我欽佩,而且提出的一些厚黑例子也確實對的上他的學說。但本書後面真的太多重複的東西,已經完全沒講到厚黑了,實在是略為可惜。


--

日前之小利害,與日後之大利害 往往相反。勞筋骨為小害,日後有大用。貪其色為小利,日後卻有後患。

2024年1月12日 星期五

Rust 迭代all概述 - 是否全部滿足條件


迭代all

all跟any[1]有一點點相似

但all是判斷全部條件是否吻合

any則是只要一個條件吻合就是true


all

文件這樣解釋all[2]

fn all<F>(&mut self, f: F) -> bool
where
    Self: Sized,
    F: FnMut(Self::Item) -> bool,

自身為一個迭代器

輸入一個閉包,閉包內為一個判斷式

最後輸出true or false


例子

假設需要判斷整個數據是否是偶數

可以這樣做

fn main() {
    let data = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
    let res = data.iter().all(|x| x % 2 == 0);
    println!("is even: {}", res);
}
is even: true

先將data放入迭代器中

並且使用any

閉包內判斷式判斷是否為偶數

最後輸出


如果data中有個奇數

則會出現這樣結果

fn main() {
    let data = vec![2, 4, 6, 8, 10, 12, 13, 16, 18, 20];
    let res = data.iter().all(|x| x % 2 == 0);
    println!("is even: {}", res);
}
is even: false


例子2

現在我們有一堆數據

這些數據表示我接收到的時間

理論上我每秒鐘接收到一筆資料

現在需要判斷是否跟理論上的一樣是每秒收到一筆資料

還是實際上有誤差

fn main() {
    let data = vec![1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15];
    let res = data.windows(2).all(|x| x[1] - x[0] == 1);
    println!("Time gap = 1: {}", res);
}
Time gap = 1: false

透過windows[3]可以判斷兩筆資料的時間

判斷第二筆時間減第一筆時間的值是否是1

最後輸出


參考資料

[1] https://lageeblog.blogspot.com/2024/01/rust-any.html

[2] https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.all

[3] https://lageeblog.blogspot.com/2023/11/rust-windows.html

Rust 迭代any概述 - 是否滿足條件


迭代any

any[1]可以判斷迭代器中是否滿足條件

文件這樣解釋

fn any<F>(&mut self, f: F) -> bool

自身為迭代器

使用一個閉包

當符合閉包條件時

輸出為true

若不符合則為false


例子

假設我想知道整個數組內有沒有奇數

可以這樣

fn main() {
    let data = vec![2,4,5,6,8,10,12,14,16,18];
    let all_even = data.iter().any(|x| x % 2 == 1);
    println!("is_even: {}", !all_even);
}
is_even: false

先把數組放入迭代器

透過any判斷迭代器中有沒有奇數

並且輸出


例子2

舉一個實際應用的例子

假設我蒐集多筆資料的時間

理論上這些資料應該都要每秒中傳一個

但我想知道是否有資料超過一秒


fn main() {
    let data = vec![1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15];
    let is_wrong = data.windows(2).any(|x| x[1] - x[0] != 1);
    println!("wrong: {}", is_wrong);
}
wrong: true

數組可以看到前面後面都是每秒傳一筆數據

但中間突然有個五秒後才傳

因此可以使用windows[2]兩個兩個比較時間

如果windows兩個相差超過一秒

則判定錯誤


參考文獻

[1] https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.any

[2] https://lageeblog.blogspot.com/2023/11/rust-windows.html


2024年1月7日 星期日

【讀後心得】墨菲定律 - 當你覺得他會出事,那他就會出事


  這本書是我近期心理學相關的書最喜歡的,書中講述了許多關於心理學的經典,不論在生活、工作、經營管理等等,總會看到可以用到的影子。作者透過多個例子講述看起來艱深難懂的心理學,要怎麼討人喜歡、要怎麼社交不被討厭、為甚麼越在意越容易失去等等。每次在生活中遇到的事物,當失敗時總覺得是運氣,但其實歸類一下會發現是自己決策可能出了一點問題。


書中講述了六十幾個心理學的名詞,其中有幾個我覺得非常不錯

墨菲定律

既然這本書叫墨菲定律,還是以這個打頭陣。墨菲定律有幾個原則

  1. 任何事情都沒有表面看到的那麼簡單
  2. 所有任務都會比預期的時間長
  3. 當他有出錯的可能,那他就有極大機率會錯誤
  4. 如果有預感會出錯,那就會出錯

  我個人認為可以把這四點大致上以"不要過於樂觀"表示,如果總是認為所有事情可以照著內心所想的行動,那總會有烙賽的一天。特別是在打程式上我總會避免墨菲定律,最近在工作時就很常遇到這種問題,即使程式是偶然性的發生BUG,等到真正要運作時總是會出事。亦或是雖然執行了上百次沒問題,但透過計算總覺得有那麼一丁點的可能性會發生錯誤,交出去的時候總會剛好發生問題。我常說不要相信客戶,當一個東西工程師都會烙賽,那到時候就是等著收到客戶的抱怨。


路徑依賴

  現在的選擇,都是依據過去的經驗而選出來的。因此常會有人說,第一份工作會嚴重影響後面的工作。人們傾向不會改變整體環境,在我看來亞洲人更是如此。也許我們受到的教育總是跟我們說得過且過,現在可以的東西就不要嘗試去動他。其實打程式也是如此,現在可以動的程式主管不會希望你去重構他。

  不過我認為這樣會有一點可惜,當有一件事想做,就該立刻去做。先嘗試再說,特別是年輕人,失敗也沒關係。我覺得最可惜的就是一堆想法卻沒有馬上下定決心要去做的人,書中有提到,只要有想要做的想法,這個東西就會一直在腦中卡住。當腦中一直留一個位置給這件事時,就不能好好休息。我覺得這個對我來說很有幫助,我總是有一大堆想法堆著,但沒有立即去作的動力。每次隔一陣子就會覺得為什麼當初沒去做,特別的可惜。


互惠互利

  這邊比較像是誘導別人思考的一種方法,也是提醒自己不要被別人誘導思考。書中有提到幾個我認為是誘導的方法

  1. 當給予一個人小恩惠,對方會有一種罪惡感想要償還
  2. 當多次確認一個人的目的,且對方同意,那通常最後不會反悔
  3. 先要求一件小事,之後慢慢增加要求不太會被拒絕
  4. 先給予一個大要求,透過討價還價慢慢降低要求

  我覺得這四個都是無謂的自尊心引起的,特別是第二個。第二個我認為就是俗稱的頭鐵,當初沒有拒絕會因為自尊而勉強繼續執行,舉個例子像是健身房,業務總是多次確認,而當興頭上時總覺得要去健身。但過了一兩個月開始慢慢變懶,又覺得當初跟業務信誓旦旦講成那樣而不好意思取消,雖然實際上業務也不會讓你取消啦。

  而第三與第四則是談判技巧,3就像是詐騙集團一樣,先騙你一點錢,之後慢慢加大也不太會拒絕。4則是砍價上常用到,舉個動畫的例子:獵人裡面的金在會長選舉的時候,先用好幾個很誇張的條件想讓大家同意,可預期的所有人都反對,於是一條一條慢慢砍掉,直到最後大家接受條件。但其實仔細思考,如果一開始就拿出最後的條件,其實根本不會有人接受。


心得

  雖然這本書叫做墨菲定律,但我覺得他其實比較像心理學的入門書。書中講到墨菲定律的章節其實只有一點點,花了很多頁數在講述各種心理學上遇到的名詞,每個篇章約是三頁或四頁。而這本書不只這三個,在寫這篇文章時重看自己的筆記,發現其實有許多地方都值得拿出來講。在整理資訊時可以使用定錨理論、在股票操作時可以使用博傻理論、如何破解囚犯困境等等,有時間實在是很想把自己寫的心得繼續整理。

推薦: ★★★★★



才剛講完有想法就要馬上去做,心得最後一句話就違反。


2024年1月6日 星期六

Rust time::OffsetDateTime數字轉成時間


time::OffsetDateTime數字轉成時間

time::OffsetDateTime[1]主要作用就是顯示日期

他可以將數字轉換成日期

也可以將日期轉換為數字

最多可有奈米精度


數字指的是Unix Time[2]

以1970年1月1日0:00:00為起始



常用的方法

UNIX_EPOCH[3]

    pub const UNIX_EPOCH: Self = _

UNIX_EPOCH就是最初始值,也就是1970年1月1號0點

use time::OffsetDateTime;

fn main() {
    println!("{:?}", OffsetDateTime::UNIX_EPOCH);
}
1970-01-01 0:00:00.0 +00:00:00


now_utc[4]

   pub fn now_utc() -> Self

now_utc就是直接輸出現在的時間

如果要改成台灣時間記得UTC+8

use time::OffsetDateTime;

fn main() {
    println!("{:?}", OffsetDateTime::now_utc());
}
2024-01-06 5:18:38.2221338 +00:00:00


from_unix_timestamp[5]

    pub const fn from_unix_timestamp(timestamp: i64) -> Result<Self, ComponentRange>

from_unix_timestamp可以將unix_timestamp轉換為日期

最後輸出是Result要unwrap

例如

use time::OffsetDateTime;

fn main() {
    let time = OffsetDateTime::from_unix_timestamp(1758634950);
    println!("{:?}", time.unwrap());
}
2025-09-23 13:42:30.0 +00:00:00

也可以使用from_unix_timestamp_nanos[6]達到奈秒精度


unix_timestamp[7]

    pub const fn unix_timestamp(self) -> i64

而unix_timestamp則是反過來

可以將日期轉換為unix timestamp

use time::OffsetDateTime;

fn main() {
    let time = OffsetDateTime::now_utc();
    let timestamp = time.unix_timestamp();
    println!("{}", timestamp);
}
1704519287

也有unix_timestamp_nanos[8]取得奈米精度



second[9]

    pub const fn second(self) -> u8

second可以獲得time的時間

例如

use time::OffsetDateTime;

fn main() {
    let time = OffsetDateTime::now_utc();
    let time_sec = time.second();
    println!("{}", time);
    println!("{}", time_sec);
}
2024-01-06 5:46:18.4763776 +00:00:00 18

同時也有year、month、day、hour、minute、millisecond、microsecond、nanosecond

use time::OffsetDateTime;

fn main() {
    let time = OffsetDateTime::now_utc();
    let time_year = time.year();
    let time_month = time.month();
    let time_day = time.day();
    let time_hour = time.hour();
    let time_minute = time.minute();
    let time_sec = time.second();
    let time_millisec = time.millisecond();
    let time_microsec = time.microsecond();
    let time_nanosec = time.nanosecond();
    println!("{}", time);
    println!("{}", time_year);
    println!("{}", time_month);
    println!("{}", time_day);
    println!("{}", time_hour);
    println!("{}", time_minute);
    println!("{}", time_sec);
    println!("{}", time_millisec);
    println!("{}", time_microsec);
    println!("{}", time_nanosec);
}
2024-01-06 5:48:54.7823054 +00:00:00 2024 January 6 5 48 54 782 782305 782305400


加減法

OffsetDateTime也可以加減

舉個例子

use time::{OffsetDateTime, Duration};

fn main() {
    let timestamp_start = OffsetDateTime::from_unix_timestamp(1704520785).unwrap();
    let timestamp_end = OffsetDateTime::from_unix_timestamp(1704520845).unwrap();
    let duration: Duration = timestamp_end - timestamp_start;
    println!("{}", duration);
}
1m

但要注意剪完會變成Duration[10]

參考資料

[1] https://docs.rs/time/latest/time/struct.OffsetDateTime.html#

[2] https://zh.wikipedia.org/zh-tw/UNIX%E6%97%B6%E9%97%B4

[3] https://docs.rs/time/latest/time/struct.OffsetDateTime.html#associatedconstant.UNIX_EPOCH

[4] https://docs.rs/time/latest/time/struct.OffsetDateTime.html#method.now_utc

[5] https://docs.rs/time/latest/time/struct.OffsetDateTime.html#method.from_unix_timestamp

[6] https://docs.rs/time/latest/time/struct.OffsetDateTime.html#method.from_unix_timestamp_nanos

[7] https://docs.rs/time/latest/time/struct.OffsetDateTime.html#method.unix_timestamp

[8] https://docs.rs/time/latest/time/struct.OffsetDateTime.html#method.unix_timestamp_nanos

[9] https://docs.rs/time/latest/time/struct.OffsetDateTime.html#method.second

[10] https://lageeblog.blogspot.com/2024/01/rust-timeduration.html