0

假设我有一个这样的列表

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
4

2 回答 2

3

这是一种使用列表理解模式匹配来做你想做的事情的安全方法

let a' = [x | (_:(_:(x:_))) <- a]

这将遍历 list 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]
于 2012-12-31T16:36:10.290 回答
0

使用最近的镜头库 (Control.lens) 的替代解决方案是:

import Control.Lens
>a^..traverse.(element 2)
["1543","1578"]

不使用中缀表示法:

>toListOf (traverse.(element 2)) a
["1543","1578"]

'traverse' 访问可遍历的每个元素,在本例中为列表,并且 (element 2) 获取索引为 2 的元素,toListOf 将其全部收集到一个列表中。这种方法的优点是,如果以后决定使您的数据结构复杂化,您只需要编写自己的镜头接口(如果它还没有的话)。

假设你有 [[(Annotation, String)]] 而不是 [[String]] 并且你只想要上面的 String 部分。那么你需要做的就是 _2 元组访问器。

a^..traverse.(element 2)._2
于 2013-01-02T22:23:39.053 回答