我正在使用活动模式来解析csv格式的使用日志中的使用事件。下面列出了活动模式部分。解析整个文件效果很好,生成的序列充满了各种UsageEvents。
type SystemName = string
type SystemVersion = string
type MAC = string
type Category = string
type Game = string
type Setting = string
type StartupLocation = string
type UsageEvent =
| SystemStart of DateTime * SystemVersion * SystemName * MAC
| SystemEnd of DateTime
| GameStart of DateTime * Category * Game * Setting * StartupLocation
| GameEnd of DateTime * Category * Game
| Other
let (|SystemStart|SystemEnd|GameStart|GameEnd|Other|) (input : string list) =
match List.nth input 0 with
| "SystemStartedEvent" ->
SystemStart (DateTime.Parse (List.nth input 1), List.nth input 2, List.nth input 3, List.nth input 4)
| "SystemEndedEvent" ->
SystemEnd (DateTime.Parse (List.nth input 1))
| "GameStartedEvent" ->
GameStart (DateTime.Parse (List.nth input 1), List.nth input 2, List.nth input 3, List.nth input 4, List.nth input 5)
| "GameEndedEvent" ->
GameEnd (DateTime.Parse (List.nth input 1), List.nth input 2, List.nth input 3)
| _ ->
Other
我遇到的问题是我可能以错误的方式使用ActivePattern。我想基于一些逻辑走出列表来创建一个树,但是在解析之后我无法匹配序列中的条目。
let CountSystemStart (entries : UsageEvent list) =
let rec loop sum = function
| SystemStart(_,_,_,_) -> sum + 1
| _ -> sum
loop 0 entries
此匹配不起作用,因为循环函数需要string list
。在其他方面,我可以使用联合中包含的数据,还是应该匹配输入,然后将其存储为常规类型?
答案 0 :(得分:6)
要添加到@Petr的答案 - UsageEvent
个案例,并且您的活动模式案例具有相同的名称,因此稍后定义的活动模式会影响联合类型。 string list
事件来自的地方,很有可能。
我只是完全删除活动模式,然后将Parse
函数(或者更确切地说是ParseParts
添加到UsageEvent
,因为您想要将字符串列表提供给它。
type UsageEvent =
| SystemStart of DateTime * SystemVersion * SystemName * MAC
| (...and so on...)
static member ParseParts (input: string list) =
match input with
| ["SystemStartedEvent"; date; version; name; mac] ->
SystemStart (DateTime.Parse date, version, name, mac)
| (...and so on...)
活跃的图案很可爱,但你真的需要一个很好的场景让它们闪耀。否则,如果您可以使用普通函数,只需使用普通函数。
答案 1 :(得分:2)
此代码存在以下两个问题:
受歧视的联合UsageEvent
和活动模式选择函数具有相同的名称
递归循环函数在写入时不是递归的 - 它不会调用自身。
当您在UsageEvent列表上匹配时,请尝试使用完整类型名称。
我会将您的CountSystemStart函数重写为:
let CountSystemStart (entries : UsageEvent list) =
let rec loop sum = function
| [] -> sum
| (UsageEvent.SystemStart(_))::rest -> loop (sum + 1) rest
| _::rest -> loop sum rest
loop 0 entries