[ 首頁 / 搜尋 / 管理Discord ] [ Komica首頁 ] [ 跨版面 ] [ 雜談 / / 攝影 / 運動 ] [ 人工智慧 / 程設交流 ] [ 蔚藍檔案 / 英雄聯盟 / 米哈遊 / Minecraft / 魔物獵人 / 勝利女神:妮姬 / Pokémon / 刀劍亂舞 / Unlight ]

/cs/ - 程設交流

Computer science
名稱
Email
主題
回覆
檔案
嵌入
Options
密碼 (用來刪除檔案。)
  • Allowed file types:jpg, jpeg, png, gif, mp4, webm
  • Max filesize is 10 MB.
  • Max image dimensions are 10000 x 10000.
  • You may upload 1 per post.

  [Go to bottom]   [Catalog]   [返回]   [Archive]   [Featured]
YouTube embed. Click thumbnail to play.

1cfe52d3 No.306

Why You Shouldn't Nest Your Code

1cfe52d3 No.307

File: 1742045127834.jpg (107.3 KB, 1000x709, httpsi.imgur.comY2fxJ9c.jpg)


574701b8 No.309

拆解、拉平雖然對可讀性有正面影響,
但反過來說也是把大量的運算資源消耗在事前檢查上。
程式要先跑完一大堆檢查之後才終於到達實際執行的階段。
我寫過檢定條件多達十多個if(每個if個有三到五組and/or/andalso/orelse…)的程式。
跑完那一大串之後才終於進入真正要做的事(大概三五行而已…)

個人心得:

波動拳問題其實跟這個時代軟體從業者的技能大多來自自學,
學習過程中也缺乏真正有能者的指導有關。
即使是專業學校或學程,也經常缺乏真正有辦法指導的講師。

造成軟體工成師偏好Nesting的原因主要有:

1. 對程式略微底層(如各種運算子)的運作方式掌握不足
2. 缺乏推理能力或意願。
3. 缺乏時間管理能力,害怕進行2的推理會導致超時,而寧願用能夠輕易理解的方式作業。

1其實意外常見,2跟3基本上雞生蛋蛋生雞。
菜鳥時期都會有這種花很多時間突破一個小問題結果時間到沒做完被罵得要死的經驗。
系統內普遍缺乏能夠告訴菜鳥「你放心,這個方向是正確的」的人是主要問題。
畢竟真的很少。

我即使到現在也常面臨:
「我很確定這件事情能夠拉平來做,但我不確定具體做法,
我是否應該投資時間在搞懂這件事情上,還是應該直接Nesting或者雙層迴圈解決」
的抉擇。

我應該不是never nester,畢竟就像前面說的,
一大堆檢查跟return之後才做那少少兩三行其實也是很有問題的。
巢狀處理的優點是可以很快速地明白相對關係以及結構,
而不用去仔細分析這前面每個if到底做了什麼。
也相對不用擔心邏輯判斷的順序導致程式無法執行。

f7b77a43 No.311

我的想法
程式碼是樹狀結構
一棵樹退化到變成linkedlist或者array都不好
重點還是要平衡

574701b8 No.313

仔細想想,把一段程式拆到另一個地方其實也還是Nesting,
而且還會在系統中留下用途單一無法重用的方法。
現在會覺得,
像 No.307的波動拳雖然看起來很醜很難讀,但實際上效能應該是最快的
(但是會寫出這種東西的水準也不會知道怎麼檢測效能),
所以實際上,除了避免過度nesting以外,
我們需要的應該是新的語法糖來把波動拳變成好讀的形式。

bf672d5f No.315

File: 1742106446959.gif (1.09 MB, 352x198, 1738198840209.gif)

>>313
仔細想想,if只不過是 cmp 和 mov

Python 讓語句更具可讀性的解決方案是將所有if變更為dictionary
C++ 的解決方案是將 {} 中的所有內容塞進一行

f7b77a43 No.316

>>315
現在python也有switch了
雖然以indent的量來說是差不多…
dictionary雖然好用,但也不是萬用解

bf672d5f No.317

>>316
對於 C#,簡短的回答是 switch 語句以線性方式執行,而dictionary以logarithm對數方式執行。

小型 switch 語句通常被實作為一系列 if-elseif 語句,比較切換變數和每個情況的相等性。

另一方面,dictionary使用索引優化集合來儲存值。在 .NET 中,Dictionary 基於 Hashtable,其具有有效的恆定存取時間(缺點是空間效率極差)。其他常用於「映射」集合(如字典)的選項包括紅黑樹等平衡樹結構,它提供對數存取(和線性空間效率)。其中任何一個都可以允許程式碼在集合中找到與正確的「if」相對應的鍵(或確定它不存在),dictionary的速度比 switch 語句執行相同操作的速度要快得多。

此外,應避免使用 switch 語句,因為它們的維護性較差。

f7b77a43 No.318

>>317
…抱歉懷疑你,不過你這是餵AI給的回答嗎?

switch維護性差是同樣一個switch到處複製重寫的情況
單就能夠重寫成dictionary的情況限定來說
把switch包在function裡之後
就只有dictionary用[],function用()的差別而已

效率還是要看語言實作
c++的switch基本上都是compile到lookup table,一般情況應該是不會比較慢
只是case多或者range比較大等等特殊的情況就會比較複雜
如果限定key是int的話還要跟array比較,然後就還要考慮記憶體快取效率問題
到這裡不實測應該很難預測結果
(我還是會先猜switch比較快就是了,畢竟內建功能通常有比較好的最佳化)
python或js之類就不知道了
畢竟這些語言本來就慢
沒有jit的話用dictionary也很合理
而且js好像有特別針對dictionary做最佳化

以debug的差別來說
switch有個可以直接step in的好處
用dictionary的話你想針對某個case設斷點就要用conditional
斷點一多就更麻煩了
(這部分是把工具學好一點就可以解決的事情就是了)

然後最後有個功能性的差別
switch的case要compile time就寫死
dictionary內容可以全部runtime決定
不過這種情況又有點降低可讀性了,因為只看code根本不知道有什麼case
最好還是有個註解或文件把可能的case都寫下來

總而言之,效率上不實測不知道,但除非你很確定你符合特殊情況或真的需要擠出那一點速度,一般情況相信compiler比較好
維護性上也沒有多少差別,不過switch更verbose一點,這邊就看喜好

回歸到上面的話題,其實用switch或dictionary跟波動拳好像沒什麼關聯…

bf672d5f No.319

>>318
不是餵AI給的回答

switch的快慢取決於語言和資料大小

dictionary[] 儲存計算值在記憶體中的各個位置。當dictionary[]找不存在的計算值時,會新增延遲。

當switch使用類似array()的連續記憶體區域時,switch可能會比dictionary[]使用的hash table更快。否則,switch速度較慢。

array()記錄大量資料時會變慢:array()將所有字串儲存在其整個範圍內的記憶體中,或在 C/C++ 等語言中手動分配內存,直到明確釋放記憶體。對於大型數組,這可能會佔用大量記憶體。

當涉及到讀取資料時:switch 讀取資料以線性時間O(n),而array()讀取資料以更快的恆定時間O(1)。hash table對於小數據是 O(1),對於不確定的大數據是 O(n)。if時間複雜度為O(1)。 nested if時間複雜度有不同意見。 從 O(1) 到 O(m*n)。最基本的nested for-loop的時間複雜度是O(n^2)。

c3096d4c No.321

是說樓上一直有人講Dictionary/HashMap,
不過以我自己的認知,if/else-if 結構最大的優勢不就是
「設計得當的時候可以避免不必要的判斷」?

變成 Dictionay / HashMap 的結構不就表示要把所有條件都檢查一遍?
這樣不是浪費一堆算力? 也難怪 case 裡的東西都會被要求是常數。

然後
>>307

這個波動拳,其實只需要放開心胸去搞清楚if-elseif 的執行方式。
完全可以用if-elseif 拉平。
這類型好像曾經是專科跟半路出家的鑑別器,
基礎不好的就很容易寫出這種東西,
有人帶的可能是很多組if或者是一片平的if-elsif。

04d068e7 No.322

File: 1742317584966.png (49.41 KB, 438x478, Screenshot_2025-03-18_09-5….png)

>變成 Dictionay / HashMap 的結構不就表示要把所有條件都檢查一遍?

都檢查一遍 ===> if key in dict: ====> O(n)

if dict.get(key): =====> O(1)

dbecdd7c No.326

>>322

老兄你這個範例會把加減乘除都算一次耶。
今天你只是加減乘除,
如果換成更複雜的計算不就全部都要跑一次?

dbecdd7c No.327

不覺得Switch/Case會難維護。
現實來說就是會有一個input有N種狀態的狀況。
會有問題的其實是遇到可以拆出去變另一個方法卻還是硬寫在一起把層數拉高,
或者判斷先後順序明確,可以用if/elsif+return卻硬要弄成狀態機用
switch/case,基本上就是這篇開頭影片在講的nesting。
雖然對電腦來說做的事情差不多,
但不可否認把原始碼的層數控制住還是會對可讀性有幫助。



[Go to top] [Catalog] [返回][Post a Reply]
刪除貼文 [ ]
[ 首頁 / 搜尋 / 管理Discord ] [ Komica首頁 ] [ 跨版面 ] [ 雜談 / / 攝影 / 運動 ] [ 人工智慧 / 程設交流 ] [ 蔚藍檔案 / 英雄聯盟 / 米哈遊 / Minecraft / 魔物獵人 / 勝利女神:妮姬 / Pokémon / 刀劍亂舞 / Unlight ]