Aro*_*Lee 1 haskell list filter
我想在地图中使用'head'功能.问题是'head'函数只接受非空列表.我有清单列表:
let ll =[["dog", "cat"], ["pig", "cow"], []]
Run Code Online (Sandbox Code Playgroud)
我需要两次迭代列表列表
let listOne = filter(\x -> if length x > 0) ll
map(\x -> head x) listOne
Run Code Online (Sandbox Code Playgroud)
我想知道我是否可以迭代列表列表一次或在地图中放入"if condition"而不使用'filter'
任何建议将不胜感激.
是的,实际上你可以把它写成列表理解语句,并使用模式匹配代替:
result = [ h | (h:_) <- ll ]
Run Code Online (Sandbox Code Playgroud)
或作为一种功能:
heads :: [[a]] -> [a]
heads ll = [ h | (h:_) <- ll ]
Run Code Online (Sandbox Code Playgroud)
所以这里我们使用(h:_)匹配所有非空列表的模式,我们直接获取h这样的列表的头部并将其添加到列表中.如果在列表推导中使用模式(在左箭头的左侧<-,它将跳过与模式不匹配的元素).
这比使用更安全length,因为length如果使用无限列表,它将陷入无限循环.此外,通过使用非总head函数的模式,我们有更多的语法保证,这个函数将起作用(是的,一旦非空元素被过滤,我们当然肯定head不会导致错误,但我们只知道这个因为我们有关于这个head功能的信息).
请注意,您的尝试将导致语法错误,因为您使用的是a if,而不是a then和elsepart.
或者,我们可以像@DanielWagner所说的那样,以heads不同的方式编写函数,例如使用:
heads :: [[a]] -> [a]
heads ll = concatMap (take 1) ll
Run Code Online (Sandbox Code Playgroud)
或者使用list monad 的绑定:
heads :: [[a]] -> [a]
heads = (take 1 =<<)
Run Code Online (Sandbox Code Playgroud)
或者我们可以转置2d列表.在这种情况下,第一行包含列表的所有头部.但由于不能保证有这样的行,我们可以在末尾添加一个空列表,如:
heads :: [[a]] -> [a]
heads = head . (++ [[]]) . transpose
Run Code Online (Sandbox Code Playgroud)