Gurkmeja101
Gurkmeja101

Reputation: 662

How do I operate on a list of lists of tuples?

I have something that looks like this:

[[('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)]]

I want to do operations on the second element of every tuple. I want to divide them by a certain number, so that it becomes a double.

I've tried using maps, so I can print just the second element of the tuples with

map (map snd) f

where f is the list above. I get the following:

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

I'm really stuck now; I can't seem to figure out what to do next and how to do operations on those.

Upvotes: 1

Views: 577

Answers (4)

Chris Martin
Chris Martin

Reputation: 30736

Using 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)]]

Upvotes: 2

Sibi
Sibi

Reputation: 48644

You just need to use two maps, one map for traversing the outer list, and the other map for traversing the inner list. Some demo in ghci to make it clear:

λ> 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)]]

Notice that the first three examples written above are equivalent. Notice how I expand each one of them. id is an identity function which will return the same output as input. In the last map expression, I apply an * 8 to the second value of the tuple. Likewise, you implement your custom operation.

Upvotes: 4

Frerich Raabe
Frerich Raabe

Reputation: 94299

The Control.Arrow module exposes a second function which you could use:

λ: 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)]]

Upvotes: 4

JHobern
JHobern

Reputation: 864

If you want to get a list that consists of all of the second elements in your tuples, you can flatten your lists, using concat, and then map snd over that new list. This will give you a list composed of all of the second elements of your tuples.

secondElements = map snd . concat

This will give you a list of all of the second elements in your tuples, and you can then map your functions over it.

Upvotes: 0

Related Questions