假设我有一个像这样的列表
let a =[["Warning:","Route","1543","must","Stop","on","Link","11881"],["Warning:","Route","1578","must","Stop","on","Link","12171"]]
我想提取其中每个列表的第三个元素,即我希望得到["1543","1578"]
我为了获得它而编写了以下代码,但它不起作用:
foldr (\acc x -> (x !! 2):acc) [] a
答案 0 :(得分:3)
使用list comprehension和pattern matching
,这是一种安全的方式来执行您想要执行的操作let a' = [x | (_:(_:(x:_))) <- a]
这将迭代列表a
,查看长度至少为3
的所有子列表,并返回每个此类子列表的第三个元素。
此解决方案将默默忽略长度小于3
的子列表。要解决这个问题并获得一些灵活性,您可以编写一个在其返回类型中使用Maybe
的函数;如果列表有第三个元素,它将返回Just
第三个元素,否则它将返回Nothing
。
takeThird :: [a] -> Maybe a
takeThird (_:(_:(x:_))) = Just x
takeThird _ = Nothing
然后,您可以使用列表解析来编写操作的安全版本:
let safea = [takeThird x | x <- a]
然后您可以创建一个可能删除元素的版本:
let maybedropa = [x | Just x <- safea]
答案 1 :(得分:0)
使用最近的lens库(Control.lens)的替代解决方案是:
import Control.Lens
>a^..traverse.(element 2)
["1543","1578"]
不使用中缀表示法:
>toListOf (traverse.(element 2)) a
["1543","1578"]
假设您[[(Annotation,String)]]代替[[String]],而您只需要像上面一样的String部分。然后你需要做的就是_2元组访问器。
a^..traverse.(element 2)._2