如何将txt文件中的值解析为OCaml中的记录列表?

时间:2015-03-30 04:18:31

标签: list parsing ocaml record

我正在尝试学习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的情况下正常工作,但在我尝试解析时失败。

2 个答案:

答案 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记录。

您的代码仍然存在很多问题,这是令人费解的,这个答案旨在帮助您运行代码,然后测试并改进它。

相关问题