one user
one user

Reputation: 109

Split list of Strings and extrat elements to a new List

I have a list of Strings like ["1,2,3", "4,5,6", "7,8,9"] and I'm trying to split the Strings in [["1","2","3"], ["4","5","6"], ["7","8","9"]] and then i'm trying to from a new list where a only have like all the second elements (from example) from the lists in a new list like [2,5,8], and then calculate the average of this elements.

My last attempt was this:

import System.IO
import Data.List

removeComa :: [String] -> [String]
removeComa [] = []
removeComa (x:xs) = splitOn "," x : removeComa xs --ERROR HERE

contentsFromCol :: [String] -> Int -> [Int]
contentsFromCol [] _ = []
contentsFromCol (x:xs) c = read x !! c ++ contentsFromCol xs c

average' :: [String] -> Int -> IO()
average' content col = do
    let contents = removeComa content
    let contents' = contentsFromCol contents col
    realToFrac (sum contents') / genericLength contents'

but I keep getting Variable not in scope: splitOn :: [Char] -> String -> String and i don't understand why?

Upvotes: 1

Views: 52

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476709

but I keep getting Variable not in scope: splitOn :: [Char] -> String -> String and i don't understand why?

Because there is no splitOn function in the Prelude, in fact there is not a splitOn in the base package.

You need to install the split package, for example with cabal install split, or by adding split to the dependencies of the stack project, and then import it from Data.List.Split:

import System.IO
import Data.List
import Data.List.Split(splitOn)

removeComa :: [String] -> [[String]]
removeComa = map (splitOn ",")

This will also return a list of list of strings, so [[String]]. In your contentsFromCol, you should use !! c on the row, not on the result of read x:

contentsFromCol :: [[String]] -> Int -> [Int]
contentsFromCol [] _ = []
contentsFromCol (x:xs) c = read (x !! c) : contentsFromCol xs c

Your average' function however does not make much sense: realToFrac … … has not as type IO (), so that will raise an error as well.

You can implement this with:

average' :: Fractional a => [String] -> Int -> a
average' content col = fromIntegral (sum contents') / genericLength contents'
    where contents' = contentsFromCol (removeComa content) col

Upvotes: 2

Related Questions