我有一个功能,有很多看起来像这样的警卫:
function
| p `elem` [0,1,2,3,4,5,6] = [0,1,2,3,4,5,6]
| p `elem` [7,8,9,10,11,12,13] = [7,8,9,10,11,12,13]
| p `elem` [14,15,16,17,18,19,20] = [14,15,16,17,18,19,20]
| otherwise = []
Run Code Online (Sandbox Code Playgroud)
我确信我可以用Haskell写得更短.如果没有,那就没关系.我是Haskell的新手,我希望通过学习不同的方法来改善它.
也许使用"地图"可能是一个好的开始?但是,我不确定如何传递这些特定的列表.
值并不总是连续的.
简单边界检查怎么样?
function p
| p < 0 = []
| p < 7 = [0..6]
| p < 14 = [7..13]
| p < 21 = [14..20]
| otherwise = []
Run Code Online (Sandbox Code Playgroud)
它会更快,并且对于某些应用程序使用更少的内存.
如果您不想执行边界检查(但是元素检查),您仍然可以使用缩短的列表表示法.
或者,您可以构造一个迭代列表的辅助函数:
helper (x:xs) p | elem p x = x
| otherwise = helper xs p
helper [] _ = []
function = helper [[0..6],[7..13],[14..20]]
Run Code Online (Sandbox Code Playgroud)
虽然这实际上更长,但您可以轻松扩展function以使用其他列表.但请注意,此函数将更慢,因为elem需要O(n)时间,而边界检查需要O(1)时间.
您也可以 - 正如@ jamshidh的回答中所建议的那样,构建一个Data.Map保证O(log n)查找时间的数据结构:
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe(fromMaybe)
helper2 :: Ord a => [[a]] -> a -> [a]
helper2 lst p = fromMaybe [] $ Map.lookup p (Map.fromList $ concatMap (\x -> zip x (repeat x)) lst)
function = helper2 [[0..6],[7..13],[14..20]]
Run Code Online (Sandbox Code Playgroud)
对于最后一篇文章,它(\x -> zip x (repeat x))为包含列表元素e和整个列表的列表元组生成生成l.例如:
Prelude> (\x -> zip x (repeat x)) [0..6]
[(0,[0,1,2,3,4,5,6]),(1,[0,1,2,3,4,5,6]),(2,[0,1,2,3,4,5,6]),(3,[0,1,2,3,4,5,6]),(4,[0,1,2,3,4,5,6]),(5,[0,1,2,3,4,5,6]),(6,[0,1,2,3,4,5,6])]
Run Code Online (Sandbox Code Playgroud)
其工作方式如下:x例如[0,1,2,3,4,5,6],与列表统一,现在我们在无限列表zip上[0,1,2,3,4,5,6]和上面应用函数[[0,1,2,3,4,5,6],[0,1,2,3,4,5,6],[0,1,2,3,4,5,6],....].zip只要两个列出feed元素,就生成元组,因此它从第一个元素[0,1,..,6]和第一个元素中获取[[0,1,..,6],[0,1,..,6],[0,1,..,6],...]结果元组(0,[0..6]),接下来它1从列表中获取第二个元素repeat,从而获取函数中的第二个元素(1,[0..6]).它一直这样做 - 虽然懒惰 - 直到其中一个列表用尽,这是第一个列表的情况.
您可以在此处使用列表monad.
func p = join $ do x <- [[1,3,5], [2,4,6], [7,8,9]]
guard $ p `elem` x
return x
Run Code Online (Sandbox Code Playgroud)
列表列表是您要检查的内容.guard过滤掉未成功选择的调用.只要候选人名单不相交,最多一个人就会成功.return x评估其中一个[]或[x]两个选项之一x,因此join
减少[x]到[].
> func 1
[1,3,5]
> func 2
[2,4,6]
> func 7
[7,8,9]
> func 10
[]
Run Code Online (Sandbox Code Playgroud)
作为列表理解,它看起来像
func p = join [x | x <-[[1,3,5],[2,4,6],[7,8,9]], p `elem` x]
Run Code Online (Sandbox Code Playgroud)