【发布时间】:2011-08-17 23:47:48
【问题描述】:
是否可以剪切字符串例如
"one , Two"
到一个列表
["one", "two"]
或者只是
"one", "two"
谢谢
【问题讨论】:
是否可以剪切字符串例如
"one , Two"
到一个列表
["one", "two"]
或者只是
"one", "two"
谢谢
【问题讨论】:
如果您不想安装split package (see Frerich Raabe's answer),这里有一个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
【讨论】:
这里常规的旧列表操作就足够了,
import Data.Char
> [ w | w <- words "one , Two", all isAlpha w ]
["one","Two"]
又名
> filter (all isAlpha) . words $ "one , Two"
["one","Two"]
列表黑客、解析和设计
在文本处理中存在一定程度的权力和权重。在最简单的情况下,基于列表的解决方案,例如上面的解决方案,提供非常少的句法噪音,以获得快速的结果(与 shell 脚本中的快速'n'dirty 文本处理相同)。
列表操作可能会变得非常复杂,您可能会考虑,例如通用的split 库,用于在任意文本上拆分列表,
> splitOn " , " "one , Two"
["one","Two"]
对于更难的问题,或不太可能被丢弃的代码,更强大的技术是有意义的。特别是,您可以通过使用解析器组合器将问题描述为语法来避免脆弱的模式匹配,例如parsec 或uu-parsinglib。随着时间的推移,通过解析器描述的字符串处理往往会导致代码更加健壮,因为随着需求的变化,修改以组合器样式编写的解析器相对容易。
关于正则表达式的注意事项:列表匹配和正则表达式在易用性和(不)安全性方面大致相同,因此出于讨论的目的,您可以用“正则表达式”代替“列表拆分”。如果代码打算长期存在,解析几乎总是正确的方法。
【讨论】:
"one |, Two" -> ["one |", "Two"] 这样的情况呢? (例如,不要使用包含非分隔符)
有一个完整的函数模块用于不同的策略来拆分列表(例如字符串,它只是一个字符列表):Data.List.Split
使用这个,你可以做到
import Data.List.Split
> splitOn " , " "one , Two"
["one","Two"]
【讨论】:
cabal install split 安装它。
未经测试,使用 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。
【讨论】: