[英]Complex nested if else statements in Haskell (Performance)
如果我想處理數億個數字並將它們通過if-else嵌套傳遞,例如(在過程中):
if( n > 0 ){
if( n > 100 ) {
if( n > 1000 ) {
return 1
}else{
return 2
}
}else{
if( n > 50 ) {
return 3
}else{
return 4
}
}else{
//more nested else cases
}
從程序上講,要獲得這些回報中的任何一個,都需要進行3次比較,以確保如果范圍設置正確(如果我現在放隨機數,不要介意),則平均情況是最佳的。 但是不確定在Haskell這樣的功能語言上,什么能帶來最佳性能(可讀性或鍵入的簡便性並不重要)。
例如,我可能可以直接編寫if else嵌套,或者對整個if路徑使用防護,例如:
| n > 1000 = 1
| n > 100 = 2
| n > 50 = 3
| n > 0 = 4
| etc
但是我想想,當n> 1000時,只有一個比較,對於0上的任何東西,等等,它的成本都將超過3。
這樣的結構可能會四次計算n> 0而不是分支:
| n > 0, n > 100, n > 1000 = 1
| n > 0, n > 100 = 2
| n > 0, n > 50 = 3
| n > 0 = 4
| etc
我也可以只使用一個函數,但是不確定函數是否便宜,因為比較起來會便宜一些。
好吧,雖然if
語句並不特別Haskellers喜歡,沒有什么與他們錯了。 也許最好的事情就是
if n > 0
then if n > 100
then if n > 1000 then 1 else 2
else if n > 50 then 3 else 4
else ...
也就是說,最好將整個比較工作從庫中委派為合適的數據類型。 實際上,這些嵌套的比較看起來很像您要對Map
進行硬編碼。
我可能會使用Map
和lookupLT
操作或類似的方法來實現此目的。 例如:
import Data.Map.Strict as M
-- use a lambda to avoid recomputing results on each call
count = \n -> snd <$> M.lookupLT n results where
results = M.fromAscList [(0,4),(50,3),(100,2),(1000,1)]
在ghci中:
> count 1
Just 4
> count 1001
Just 1
> count (-300)
Nothing
如果您的鍵碰巧是Int
,則可以通過在IntMap
進行交換來使其速度更快。
這應該使您獲得的結果與最佳比較數非常接近-在IntMap
情況下,甚至可能比嵌套的ifs還要少。 我不知道這種方法不一定是最快的方法,但是它是相當“識字的”:這段代碼的讀者將不必解密深層的ifs鏈來發現它的作用,然后在以后修改可能的結果(如果需要的話)將非常簡單。
您可以定義適當的決策樹:
data Tree n rv = Leaf rv | Node n (Tree n rv) (Tree n rv)
您的示例將被編碼為
(Node 0 ({- else nodes -}) -- depending on your other cases
(Node 100 (Node 50 (Leaf 4) (Leaf 3))
(Node 1000 (Leaf 2) (Leaf 1)))
(左和右子樹與<
和>=
對應。如果要進一步區分>
和==
可能需要進行一些調整。)
遍歷樹,您將n
值與每個節點中的第一個值進行比較,返回第二個值或遞歸遍歷相應的子樹。
search :: (Eq a, Ord a) => a -> Tree a b ->b
search _ (Leaf x) = x
search x (Node y left right)| x < y = search x left
| otherwise = search x right
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.