如果我想处理数亿个数字并通过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等等的任何东西,它将花费超过三个。
这样的结构可能会四次评估n> 0,而不是分支:
| n > 0, n > 100, n > 1000 = 1
| n > 0, n > 100 = 2
| n > 0, n > 50 = 3
| n > 0 = 4
| etc
我也可以使用一个函数,但不确定函数是否便宜,因为比较会。
答案 0 :(得分:3)
嗯,尽管Haskellers并不特别喜欢if
语句,但是没有错误与它们相关。也许最好的事情就是
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
进行硬编码。
答案 1 :(得分:2)
我可能会使用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
s,则可以通过交换IntMap
来使其快一点。
这应该给你一些非常接近最佳比较次数的东西 - 在IntMap
的情况下,甚至可能比你的嵌套ifs更少。我不知道这种方法必然是最快的,但它非常“有文化”:这段代码的读者不必破译深层嵌套的ifs链来发现它的作用,并在以后修改可能的结果(如果需要的话)会很简单。
答案 2 :(得分:1)
您可以定义适当的决策树:
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