我正在尝试使用Haskell来处理我想要分析的一些数据。这些数据主要是结构化的,但不一致。日期可能有许多表示形式,但总是在相同的位置(文档是XML)。
到目前为止我看到的不同格式是:
“1971年2月25日”
“星期四。6月22日。1972年。”
“7月3日。1973年。”
“10月17日星期四\ r \ n 1974年。”
“1976年3月5日星期五。”
“4月25日\ r \ n 1977.”
“1983年12月6日星期二”
“1988年5月10日”
“1988年10月20日”
我真的不知道从哪里开始 - 我可以处理的任何个别格式,但我不知道如何处理所有这些格式。我想要一个函数String - >也许是Day。
答案 0 :(得分:1)
首先解决每个问题,并将自己局限于其中一个解析器。 首先为这个解析器编写一些测试。
在Haskell中解析与在其他语言中解析完全不同,通常使用正则表达式或其他方法。在haskell中,我们拥有提供解析器组合的优秀库。我使用的是parsec
和attoparsec
。
为每个数据类型创建数据类型或使用现有的time - 包。
为每个月(Jan
或Feb
...)编写一个解析器,然后将它们组合起来。
但请注意,March
和May
都以相同的字母开头
你需要的不仅仅是简单的组合。 January
,June
和July
现在你应该有Parser Day
,Parser Month
和Parser Year
,甚至可能Parser Weekday
。
Parser Day
最后一点,有很多parsec
/ attoparsec
的教程,只是使用你最不信任的搜索引擎。
答案 1 :(得分:1)
hackage上有几个用于解析日期的库:
Data.Dates中的parseDate
功能。
Data.Time.Format中的parseTime
功能。
然后你可以将几个这样的解析器链接在一起。这是一个手动“替代”运算符:
-- Chain operator: if p1 returns Nothing, then return p2
p1 <||> p2 = case p1 of
Nothing -> p2
Just r -> Just r
所以你要为每种格式编写一个解析函数:
p1 :: String -> Maybe Day
然后将这些结合起来:
parseDate :: String -> Maybe Day
parseDate = p1 <||> p2 <||> p3
如果您编写了正确的Parser,则可以从<|>
免费获得此替代运算符(Control.Applicative
)。这是编写自己的解析器的tutorial。
我还建议通过消除标点符号甚至“rd”格式来预处理原始文本,以使其更加健壮并减少您必须编写的解析函数的数量。如果您需要更好的性能,也请考虑使用Data.Text。