How to get the first item from each list in a list of lists

2

I'm new to programming in Haskell, and wanted to know a way to get the first item from each list and put it on a list, then the second, then the third, and so on ... An example would be more less the following:

Input: [[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4]]. 
Output: [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]. 

Being that I can not import anything, just being able to use what I have in Prelude, I searched a lot on the internet and even found a function that took the first item from each list, but it was not enough for the problem.     

asked by anonymous 01.07.2018 / 21:12

1 answer

2

You can create a function like this using more general functions like map , fst , snd and splitAt , all of which are in Prelude.

primeiros :: [[a]] -> [[a]]
primeiros xs = helper1 ([], xs)

helper1 :: ([[a]],[[a]]) -> [[a]]
helper1 (hs, []) = hs
helper1 (hs, ls) = helper1 ((f2 . f1 $ ls) : hs, checaNull (f3 . f1 $ ls))
  where f1 y = map (splitAt 1) y
        f2 y = concat $ map fst y
        f3 y = map snd y
        checaNull [] = []
        checaNull ls@(x:xs) = if not (null x) then ls else checaNull xs

This is a simple but very inefficient implementation. It is inefficient because

  • Each time helper1 is called, the list is traversed twice: once in f2 . f1 $ ls and another in f3 . f1 $ ls .
  • The higher the input list, the longer the time consumed by f2 due to concat .

The result also comes out slightly different. I changed the example to show the difference:

*Main> lista = [[1,10,100,1000],[2,20,200,2000,2],[3,30,300,3000],[4,40,400,4000,4]]
*Main> primeiros lista
[[2,4],[1000,2000,3000,4000],[100,200,300,400],[10,20,30,40],[1,2,3,4]]

If you want to invert the output order, simply type helper1 (hs, []) = reverse hs as the first default of helper1 , which increases the processing time because you will need to scroll through the entire output list.

    
03.07.2018 / 08:33