如何将文本文件(CSV)解析为haskell,以便对其进行操作?

时间:2014-08-23 16:40:04

标签: haskell

我有一个平面文本文件,格式如下:

ID|COUNT|Desc
1|100|Something
2|100|More
1|15|Whatever

我需要将它加载到Haskell中以便我可以执行一些操作(在GROUP-BY ID和SUM COUNT的情况下)并且我正在寻找方法 - 有一件事我不能使用任何额外的模块/包(这是一个学校项目 - 试图通过内置的任何内容来解决这个问题。)

我正在进行一些研究,发现Text.CSV是一个选项,但我不能真正理解它是如何工作的(无法找到任何例子 - 这是可怕的) - 在我花了很多时间之前想知道这是否是正确的方法 - 任何建议,想法或例子将不胜感激。

请记住,无论如何存储,我都必须以某种方式处理数据。


我现在正在尝试这种方法:

main::IO()
main = do
       dbSales <- readFile "la.txt"
       let sales = lines dbSales
       (result, x, y) <- mapify sales
       print result

mapify :: [String] -> Map Int Int
mapify = Prelude.foldr (\s m -> let (id:count:desc) = (splitWhen (=='|') s)
                                    i = read id
                                    c = read count
                                 in insertWith (+) i c m) empty

然而,它抱怨我称之为mapify的行:

Couldn't match type `Map Int' with `IO'
Expected type: IO Int
  Actual type: Map Int Int

尝试使用新的输入文件而不确定原因但是如果我使用以下输入错误 -

ID1|ID2|DATE|SUM
0|0|07/13/2014/100
0|1|07/13/2014/101
0|2|07/13/2014/102
1|0|07/13/2014/100

而现在我试图将ID2和SUM分组(而不是上一个例子中的od ID和COUNT):

mapify :: [String] -> Map Int Int
mapify = Prelude.foldr (\s m -> let (id1:id2:date:sum) = (splitWhen (=='|') s)
                                    i = read id1
                                    j = read id2
                                    k = read date
                                    c = read sum
                                  in insertWith (+) j c m) empty

但无论我尝试什么,我都会遇到这样的错误:

Couldn't match type `[Char]' with `Char'
Expected type: String
  Actual type: [[Char]]
In the first argument of `read', namely `sum'
In the expression: read sum
In an equation for `c': c = read sum

1 个答案:

答案 0 :(得分:1)

mapify :: [String] -> Map Int Int
mapify = foldr (\s m -> let (id:count:desc) = (splitWhen (=='|') s)
                            i = read id :: Int
                            c = read count :: Int
                        in insertWith (+) i c m) empty

我认为这应该是你想要的。它将每个字符串的前两个值读入Ints,然后insertWith将id添加到地图中(如果它不存在),或者增加当前计数(如果不存在)。因为它会因格式不正确的数据而崩溃,所以您可能想要解决这个问题,它需要Data.List.SplitData.Map