2011-11-25 36 views
9

我需要在Haskell中的字符串标记器,但有显然什么都没有在Prelude或其他模块中定义。在Data.Text中有splitOn,但是使用起来很麻烦,因为你需要将String包装为Text。Haskell字符串标记器函数

令牌化器不是很难做,所以我写了一个(它不处理多个相邻的分隔符,但它对我所需要的很有效)。我觉得这样的事情应该是已经在某处模块..

这是我

tokenizer :: Char -> String -> [String] 
tokenizer delim str = tokHelper delim str [] 

tokHelper :: Char -> String -> [String] -> [String] 
tokHelper d s acc 
    | null pos = reverse (pre:acc) 
    | otherwise = tokenizer d (tail pos) (pre:acc) 
     where (pre, pos) = span (/=d) s 

版本我寻找更多的解决方案,互联网和发现了一些讨论,比如this blog post

最后的评论(由Mahee于2011年6月10日发布)特别有趣。为什么不使用更通用的单词来处理这个问题?我试图寻找这样的功能,但没有发现..

是否有一个更简单的方法来这或“标记”一个字符串不是一个非常反复的问题? :)

+0

我不是一个Haskell程序员,所以拿这个机智一粒盐。但是,我认为你所描述的情况可能被认为是足够简单的实现,即使它比“单词”更复杂。大部分其他解析任务超出“单词”级别,可能会足够复杂,而不是像解析器组合器(例如parsec)那样值得做。 – Gian

+2

我实际上推荐几乎所有的代码,你使用文本而不是字符串。这是一个性能更好的图书馆。如果您对此声明有更多疑问,我会通过电子邮件发送给咖啡馆。 –

+0

你对此绝对正确:)谢谢。我刚才在使用惰性IO时遇到了一些问题(尝试了几个小时才使它与getContents和getLine一起工作,在网上阅读等)。但是在文本上使用相同的功能,我的问题立即得到解决。我不知道如果我使用文本,性能会变差,但最终我的应用程序没有明显的差异。我将不得不研究文本如何更详细地工作:) – Adi

回答

15

split library是你所需要的。使用cabal install split进行安装,然后您可以访问大量分割/标记器样式函数。

从库中的一些例子:

> import Data.List.Split 
> splitOn "x" "axbxc" 
["a","b","c"] 
> splitOn "x" "axbxcx" 
["a","b","c",""] 
> endBy ";" "foo;bar;baz;" 
["foo","bar","baz"] 
> splitWhen (<0) [1,3,-4,5,7,-9,0,2] 
[[1,3],[5,7],[0,2]] 
> splitOneOf ";.," "foo,bar;baz.glurk" 
["foo","bar","baz","glurk"] 
> splitEvery 3 ['a'..'z'] 
["abc","def","ghi","jkl","mno","pqr","stu","vwx","yz"] 

来自同一个库中的wordsBy功能是words仿制像你想:

wordsBy (=='x') "dogxxxcatxbirdxx" == ["dog","cat","bird"] 
+0

谢谢,这正是我所需要的 – Adi