How to pick the first item from each list from a list list

Asked

Viewed 303 times

3

I’m new to programming at Haskell, and I wanted to know a way to take 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 or 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, only being able to use what has in Prelude, I searched a lot in the internet and I even found a function that took the first item of each list, but it was not enough for the problem.

1 answer

3

It is possible to create such a function using more general functions such as map, fst, snd and splitAt, all continas 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 rather inefficient implementation. It is inefficient because

  • every time helper1 is called, the list is crossed twice: once in f2 . f1 $ ls and another in f3 . f1 $ ls.
  • the longer the entry list, the longer the time consumed by f2 due to concat.

The result also comes out a little 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 reverse the output order, just write helper1 (hs, []) = reverse hs as the first standard of helper1, which increases the processing time because you will need to go through the entire output list.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.