Sibi
Sibi

Reputation: 48644

Create New List from List of [String] in Haskell

Assuming I have a list like this

let a =[["Warning:","Route","1543","must","Stop","on","Link","11881"],["Warning:","Route","1578","must","Stop","on","Link","12171"]]

And I want to extract third element of each list inside it, i.e I want to get the resultant as ["1543","1578"]

I wrote the following piece of code for obtaining it, but it is not working:

foldr (\acc x -> (x !! 2):acc) [] a

Upvotes: 0

Views: 195

Answers (2)

Davorak
Davorak

Reputation: 7444

An alternative solution using the recent lens library (Control.lens) would:

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

Not using the infix notation:

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

'traverse' visits each element of a traversable, in this case the list, and (element 2) grabs the element with the 2 index and toListOf gathers it all into a list. This method has the advantage that if decide to complicate your data structure later you just need to write your own lens interface to it if it does not already have one.

Let say instead of a [[String]] you have [[(Annotation, String)]] and you just want the String portion just like above. Then all you need to do is the _2 tuple accessor.

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

Upvotes: 0

seliopou
seliopou

Reputation: 2916

Here's a safe way to do what you want to do using a list comprehension and pattern matching

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

This will iterate over the list a, look at all sublists of length at least 3, and return the third element of each such sublist.

This solution will silently ignore sublists of length less than 3. To work around this, and gain some flexibility, you can write a function that uses Maybe in its return type; if the list has a third element, it will return Just the third element, otherwise it will return Nothing.

takeThird :: [a] -> Maybe a
takeThird (_:(_:(x:_))) = Just x
takeThird _             = Nothing

Then, you can write a safe version of your operation using a list comprehension:

let safea = [takeThird x | x <- a]

And from that you can create a version that may drop elements:

let maybedropa = [x | Just x <- safea]

Upvotes: 3

Related Questions