我正在尝试学习OCaml,并且难以将文件解析为记录列表。假设我有一个文本文件,格式如下:
吉姆鲍勃,红色 史蒂夫布莱克,蓝色等。
我希望能够将csv解析为一个记录列表,然后我将用它来进行基本列表操作,例如排序,记录为:
type person_info =
{
name : string;
favorite_color : string;
}
我有解析功能:
let parse_csv =
let regexp = Str.regexp (String.concat "\\|" [
"\"\\([^\"\\\\]*\\(\\\\.[^\"\\\\]*\\)*\\)\",?";
"\\([^,]+\\),?";
",";
]) in
fun text ->
let rec loop start result =
if Str.string_match regexp text start then
let result =
(try Str.matched_group 1 text with Not_found ->
try Str.matched_group 3 text with Not_found ->
"") :: result in
loop (Str.match_end ()) result
else
result in
List.rev ((if
try String.rindex text ',' = String.length text - 1
with Not_found -> false
then [""] else [])
@ loop 0 [])
那会把一切都分给我。但是我不知道如何将内容读入记录列表中,我甚至无法将其正确解析为数组:
let () =
let ic = open_in Sys.argv.(1) in
let lines = ref [] in
try
while true do
lines := Array.of_list (parse_csv (input_line ic))
done
with End_of_file ->
close_in ic
这可以在不调用parse_csv的情况下正常工作,但在我尝试解析时失败。
答案 0 :(得分:1)
请注意,您可以使用opam install csv
安装exists a CSV module。然后,您可以轻松读取文件(在交互式toploop中):
# #require "csv";;
/home/chris/.opam/system/lib/csv: added to search path
/home/chris/.opam/system/lib/csv/csv.cma: loaded
# let c = Csv.load "data.csv";;
val c : Csv.t = [["Jim Bob"; "red"]; ["Steve Black"; "blue"]]
然后,您可以轻松将其转换为您喜欢的格式:
# let read_people fname =
Csv.load fname
|> List.map (function [name; favorite_color] -> {name; favorite_color }
| _ -> failwith "read_people: incorrect file");;
val read_people : string -> person_info list = <fun>
# read_people "data.csv";;
- : person_info list =
[{name = "Jim Bob"; favorite_color = "red"};
{name = "Steve Black"; favorite_color = "blue"}]
答案 1 :(得分:0)
我会在这样的* nix系统上启动你的脚本 - 适合测试:
#!/usr/bin/env ocaml
#use "topfind";;
#require "str";;
然后测试你的脚本。错误消息显示
File "./so_howdoyouparse.ml", line 37, characters 13-54:
Error: This expression has type string array
but an expression was expected of type 'a list
下次在您的问题中添加错误消息。
是的,确实,为什么要尝试将Array.of_list分配给使用空列表初始化的引用?这一行可以是:
lines := (parse_csv (input_line ic)) :: !lines
然后你有某事正在工作。通过我的编辑(返回行的内容),我得到了:
val myresult : string list list =
[["Steve Black"; " blue"]; ["Jim Bob"; " red"]]
您忘了使用person_info记录。
您的代码仍然存在很多问题,这是令人费解的,这个答案旨在帮助您运行代码,然后测试并改进它。