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

如何将文本文件(CSV)解析为haskell,以便对其进行操作?,haskell,Haskell,我有一个格式如下的平面文本文件: ID|COUNT|Desc 1|100|Something 2|100|More 1|15|Whatever 我需要将其加载到Haskell中,以便我可以执行一些操作(在按ID分组和求和计数的情况下),我正在寻找方法来做到这一点-有一件事我不能使用任何其他模块/包(这是一个学校项目-尝试用内置的东西来解决) 我做了一些研究,发现Text.CSV是一个选项,但我不能真正理解它是如何工作的(也找不到任何例子-这很可怕)-在我花了很多时间在那里思考这是否是正确的方法

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

ID|COUNT|Desc
1|100|Something
2|100|More
1|15|Whatever
我需要将其加载到Haskell中,以便我可以执行一些操作(在按ID分组和求和计数的情况下),我正在寻找方法来做到这一点-有一件事我不能使用任何其他模块/包(这是一个学校项目-尝试用内置的东西来解决)

我做了一些研究,发现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

尝试使用新输入文件,但不确定原因,但出现错误-如果使用以下输入:

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和计数):

但不管我怎么做,我总是会犯这样的错误:

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

我想这应该是你想要的。它将每个字符串的前两个值读入Ints,然后insertWith将id添加到映射中(如果不存在),或者增加当前计数(如果存在)。因为它会因格式错误的数据而崩溃,所以您可能需要修复它,它需要
data.List.Split
data.Map

您可以使用
data.List.Split
将字符串沿管道拆分,然后将前两个字段读入数据类型。但是使用Data.Map从ID映射到计数可能会更容易,而不是您自己收集的
项目
s.@AndrewC我被告知我可以使用内置模块,如Map、LIST、ARRAY,无需第三方或任何其他下载或东西
let sales=tail(lines dbSales)
而不仅仅是
行dbSales
可能会解决它。@genisage我欠你一大笔钱。。。非常感谢您在概念验证方面提供的所有帮助—现在根据您的想法将其放大—非常感谢,因为
sum
是您的字符串列表中剩余的所有字符串的列表。使其成为
(id1:id2:date:sum:rest)
。或者更好,因为您没有使用
i
k
使其成为
(\uId2:\uSum:rest)
,并摆脱不必要的
读取。(即使
sum
是最后一个字段,它仍然是一个由一个字符串组成的列表,并且read不会对列表列表进行操作。)首先,喜欢这个名称(mapify)。所以要在这里测试它,我需要打开我的文件,然后逐行遍历它,对于每一行调用mapify,对吗?我的意思是,我有两种方法来完成这个初始部分,我可以使用readFile,然后使用行来插入行列表,或者我需要写一些讨厌的循环,用hGetLine和他的“foldr”做点什么。它可以引用“Prelude.foldr”或“Data.Map.foldr”。它应该是Prelude。您有两个选项,可以
导入数据。映射隐藏(foldr)
,您可以键入
Prelude.foldr
,或者
导入符合条件的数据。映射为M
,然后将
M.
放在映射的所有内容前面。发生这种情况是因为您可以从不同的库访问两个
foldr
,haskell希望您告诉它使用哪一个。
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
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