如何操作元组列表列表?

时间:2015-09-02 10:27:29

标签: list haskell

我有一些看起来像这样的东西:

[[('A',2), ('C',0), ('G',0), ('T',0)]
,[('A',0), ('C',2), ('G',0), ('T',0)]
,[('A',0), ('C',0), ('G',2), ('T',0)]
,[('A',0), ('C',0), ('G',0), ('T',2)]]

我想对每个元组的第二个元素进行操作。我想把它们除以一定数量,这样就变成了双倍。

我尝试过使用地图,所以我只能打印元组的第二个元素

map (map snd) f

其中f是上面的列表。我得到以下内容:

[[2,0,0,0],[0,2,0,0],[0,0,2,0],[0,0,0,2]]

我现在真的被困住了;我似乎无法弄清楚接下来该做什么以及如何对这些做些什么。

4 个答案:

答案 0 :(得分:4)

您只需要使用两个地图,一个地图用于遍历外部列表,另一个地图用于遍历内部列表。 ghci中的一些演示要明确:

λ> let x = [[('A',2),('C',0),('G',0),('T',0)],[('A',0),('C',2),('G',0),('T',0)]]
λ> map (map id) x
[[('A',2),('C',0),('G',0),('T',0)],[('A',0),('C',2),('G',0),('T',0)]]
λ> map (\y -> map id y) x
[[('A',2),('C',0),('G',0),('T',0)],[('A',0),('C',2),('G',0),('T',0)]]
λ> map (\y -> map (\(a,b) -> (a,b)) y) x
[[('A',2),('C',0),('G',0),('T',0)],[('A',0),('C',2),('G',0),('T',0)]]
λ> map (\y -> map (\(a,b) -> (a,b * 8)) y) x
[[('A',16),('C',0),('G',0),('T',0)],[('A',0),('C',16),('G',0),('T',0)]]

请注意,上面写的前三个示例是等效的。请注意我如何扩展它们中的每一个。 id是一个标识函数,它将返回与输入相同的输出。在上一个map表达式中,我将* 8应用于元组的第二个值。同样,您实现自定义操作。

答案 1 :(得分:4)

Control.Arrow模块公开了一个second函数,你可以使用它:

λ: let xs = [[('A',2), ('C',0), ('G',0), ('T',0)]]
λ: map (map (second (/ 3))) xs
[[('A',0.6666666666666666),('C',0.0),('G',0.0),('T',0.0)]]

答案 2 :(得分:2)

使用lens

λ: import Control.Lens
λ: import Control.Lens.Traversal
λ: let input = [[('A',2)],[('G',0),('T',1)]]
λ: over (mapped.mapped._2) ((/ 4).fromIntegral) input
[[('A',0.5)],[('G',0.0),('T',0.25)]]

答案 3 :(得分:0)

如果您想获得包含元组中所有第二个元素的列表,可以使用concat,然后map snd对新列表展平列表。这将为您提供一个由元组的所有第二个元素组成的列表。

secondElements = map snd . concat

这将为您提供元组中所有第二个元素的列表,然后您可以在其上映射您的函数。