解析逗号分隔文本
来源:互联网 发布:排卵期计算法 编辑:程序博客网 时间:2024/05/09 07:28
解析逗号分隔文本
在这一节,我将考虑两种简单的方法解析逗号分隔文本。逗号分隔(comma separated values,CSV)格式,是以文本格式保存数据的一种方法,逗号用于界定保存在每一列中的值,它是一种最古老的文本格式,在 PC 还没有标准规范的时代就已经在使用了。逗号分隔文本真正复杂的是处理转义字符,以及列中包含逗号。在这种情况下,需要考虑如何解码列,使它不会产生新列。然而,我们不考虑这种情况,因为我们将使用解析器工具,如fslex.exe、fsyacc.exe 和 FParsec。
一个有用的逗号分隔文本解析器,必须以表格形式返回文件数据,用 F# 写只要几行:
open System.IO
let parseFile filename =
letlines = File.ReadAllLines filename
seq{ for line in lines -> line.Split(',') }
这个示例使用了.NET BCL 库,去打开文件,然后,使用 F# 序列表达式和字符串的Split 方法创建数组序列,包含了列中的值。虽然这种方法很简单,也工作得相当好,但是,也有一些不足。首先,不能保证每一行的列数相同,其次,结果的类型都是字符串,因此,代码的用户必须处理值的转换。
为了解决这两个问题,可以创建逗号分隔文本解析器类,使用F# 反射动态创建强类型元组。其基本思想是这样的,级这个类一个类型参数,它必须是元组,这个类使用反射决定元组中有什么元素,以及应该如何解析这些元素;然后,把这个信息用于解析给定文件中的每一行;最后,实现IEnumerable<'a> 接口,让客户端代码能够很容易枚举产生的元组列表。反射的使用说明类的实现不简单:
open System
open System.IO
open System.Collections
open System.Reflection
open Microsoft.FSharp.Reflection
// a class to read CSV values from afile
type CsvReader<'a>(filename) =
// fail if the gernic type is no a tuple
do ifnot (FSharpType.IsTuple(typeof<'a>)) then
failwith "Type parameter must be a tuple"
// get the elements of the tuple
let elements = FSharpType.GetTupleElements(typeof<'a>)
// create functions to parse a element of type t
let getParseFunct =
match t with
| _ when t =typeof<string>->
// for string types return a function that down
// casts to an object
fun x -> x :>obj
| _ ->
// for all other types test to see if they have a
// Parse static method and use that
let parse = t.GetMethod("Parse",
BindingFlags.Static |||
BindingFlags.Public,
null,
[| typeof<string>|],
null)
fun (s: string)->
parse.Invoke(null, [| box s |])
// create a list of parse functions from the tuple'selements
let funcs = Seq.map getParseFunc elements
// read all lines from the file
let lines = File.ReadAllLines filename
// create a function parse each row
let parseRow row =
let items =
Seq.zip (List.ofArray row)funcs
|> Seq.map (fun(ele, parser)-> parser ele)
FSharpValue.MakeTuple(Array.ofSeq items, typeof<'a>)
// parse each row cast value to the type of the given tuple
let items =
lines
|> Seq.map (funx -> (parseRow(x.Split(','))) :?>'a)
|> Seq.toList
// implement the generic IEnumerable<'a> interface
interfaceseq<'a>with
memberx.GetEnumerator() =
let seq = Seq.ofList items
seq.GetEnumerator()
// implement the non-generic IEnumerable interface
interfaceIEnumerable with
memberx.GetEnumerator() =
let seq = Seq.ofList items
seq.GetEnumerator() :> IEnumerator
然而,只要完成类的实现以后,就可以以强类型的方式,用它来处理逗号分隔文本文件中的数据,且非常简单。
System.IO.Directory.SetCurrentDirectory (__SOURCE_DIRECTORY__)
let values = newCsvReader<int*int*int>("numbers.csv")
for x, y, z in values do
assert (x + y= z)
printfn "%i + %i = %i" x y z
[
第一句,是原文中没有的。
加上以后,调试起来比较方便,只要把文本文件numbers.csv 与源程序文件放在同一个目录下就可以了;否则,系统会在 %temp% 目录下查找这个文件。
]
- 解析逗号分隔文本
- c++逗号分隔符文本读取
- CSV逗号分隔符文件解析
- C++ 读取和解析逗号分隔数据
- 笔试:解析用逗号分隔的输入数据
- Javascript 数字逗号分隔
- 逗号分隔数据替换
- 将一行逗号分隔的文本分成多行记录的SQL语句
- excel数据生成txt逗号分隔文本及末尾添加新列
- C语言从txt文本中读取多行用逗号分隔的数据
- java读取csv文件内容(逗号分隔、回车换行文本)
- mysql 逗号分隔的id转为逗号分隔的名称
- 逗号分隔的值--CSV
- CSV逗号分隔值文件
- 匹配逗号分隔的内容
- 拼接字符串,逗号分隔技巧
- 正则表达式逗号分隔 (c++)
- sql字符串已逗号分隔
- ood学习笔记
- shop++修改文章页面生成路径的方法
- 学生聚类分析思考
- 学习-子网掩码
- LeetCode-Longest Valid Parentheses
- 解析逗号分隔文本
- MVC三层模型(struts+spring+hibernate)总结
- 关于meta viewport中target-densitydpi属性
- cocos2d-x项目打包发布到Win8应用商店
- The filter pushed in subquery issue in oracle 11G (filter推进子查询)
- 微信公众账号开发项目小结(五) ——如何使TokenAccess长期有效
- PHP处理IOS交易认证模块,发送数据认证功能
- 第2次实验——算法基本功 与 综合思考
- MongoDB释放2.4版本:692更新及8大得意之作