从Haskell中的[String]列表创建新列表

时间:2012-12-31 10:26:22

标签: haskell

假设我有一个像这样的列表

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

2 个答案:

答案 0 :(得分:3)

使用list comprehensionpattern 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"]
'traverse'访问遍历的每个元素,在本例中是列表,(元素2)使用2索引抓取元素,并且toListOf将其全部收集到列表中。这种方法的优点是,如果以后决定使数据结构复杂化,只需要编写自己的镜头接口(如果还没有)。

假设您[[(Annotation,String)]]代替[[String]],而您只需要像上面一样的String部分。然后你需要做的就是_2元组访问器。

a^..traverse.(element 2)._2