在Haskell中将字符串切割成列表?

4

能否截取字符串,例如

"one , Two"

转换为列表

["one", "two"]

或者只是
"one", "two"

谢谢

4个回答

6

有一整个模块的函数,用于不同的列表分割策略(如字符串,它只是一个字符列表):Data.List.Split

使用该功能,您可以执行以下操作:

import Data.List.Split

> splitOn " , " "one , Two"
["one","Two"]

由于某些原因,我没有导入那个。 - Tom
@Tom:在Haskell平台上它不是默认安装的。但是,你可以通过cabal install split来安装它。 - Joey Adams

2

在这里,普通的列表操作就足够了。

import Data.Char

> [ w | w <- words "one , Two", all isAlpha w ]
["one","Two"]

aka

> filter (all isAlpha) . words $ "one , Two"
["one","Two"]

列表操作、解析和设计

在文本处理中,有一种权力和重量的规模。最简单的基于列表的解决方案(如上面的示例)提供了非常少的语法噪音,以获取快速结果(与shell脚本中的快速文本处理相同)。

列表操作可以变得非常复杂,您可以考虑使用通用的split库,在任意文本上拆分列表。

> splitOn " , " "one , Two"
["one","Two"]

对于更困难的问题或者不太可能被放弃的代码,更加健壮的技术是有意义的。特别是,您可以通过使用解析器组合器(例如parsecuu-parsinglib)将问题描述为语法来避免脆弱的模式匹配。通过解析器描述的字符串处理倾向于随着时间的推移导致更加健壮的代码,因为在需求发生变化时修改以组合器风格编写的解析器相对容易。
关于正则表达式的注释:列表匹配和正则表达式在使用和(不)安全性方面大致等价,因此在本讨论中,您可以用"regex"替换"list splitting"。如果代码的寿命较长,则解析几乎总是正确的方法。

+1,但是......针对类似于 "one |,Two" -> ["one |","Two"] 这种情况怎么处理?(例如:不要使用非分隔符的包含) - user166390
问题未明确定义。 - Don Stewart
当然 :-) 但是如果有一个可以覆盖我的测试用例的解决方案会很好,比如在Haskell中是否有类似于“string.split”的惯用方法?(或者通过动态序列匹配拆分任何列表的更通用的方法)。 - user166390
增加了一些字符串操作方法的讨论。 - Don Stewart

2

如果你不想安装split package可查看Frerich Raabe的答案),这里有一个轻量级的splitOn函数实现:

import Data.List

splitOn :: Eq a => [a] -> [a] -> [[a]]
splitOn []    _  = error "splitOn: empty delimiter"
splitOn delim xs = loop xs
    where loop [] = [[]]
          loop xs | delim `isPrefixOf` xs = [] : splitOn delim (drop len xs)
          loop (x:xs) = let (y:ys) = splitOn delim xs
                         in (x:y) : ys
          len = length delim

0

未经测试,使用Parsec。可能还有一个正则表达式分隔符。

firstElement :: Parser String
firstElement = many $ noneOf ' '

otherElement :: Parser String
otherElement = do many $ char ' '
                  char ','
                  many $ char ' '
                  firstElement

elements :: Parser [String]
elements = liftM2 (:) firstElement (many otherElement)

parseElements :: String -> [String]
parseElements = parse elements "(unknown)"

清理otherElement会很好,类似于我使用liftM2折叠elements的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接