功能上用分隔符分隔字符串的最佳方法是什么?
我试图通过1功能上用分隔符分隔字符串的最佳方法是什么?
写在Haskell程序,将采取由逗号定界整数一串数字,将其转换为整数的列表,并增加每个号码例如 "1,2,-5,-23,15" -> [2,3,-4,-22,16]
下面是生成的程序
import Data.List
main :: IO()
main = do
n <- return 1
putStrLn . show . map (+1) . map toInt . splitByDelimiter delimiter
$ getList n
getList :: Int -> String
getList n = foldr (++) [] . intersperse [delimiter] $ replicate n inputStr
delimiter = ','
inputStr = "1,2,-5,-23,15"
splitByDelimiter :: Char -> String -> [String]
splitByDelimiter _ "" = []
splitByDelimiter delimiter list =
map (takeWhile (/= delimiter) . tail)
(filter (isPrefixOf [delimiter])
(tails
(delimiter : list)))
toInt :: String -> Int
toInt = read
对我来说,最困难的部分是一个字符串并将返回字符串
列表的功能splitByDelimiter
编程
"1,2,-5,-23,15" -> ["1","2","-5","-23","15"]
认为它工作,我不满意它的写法。有很多括号,所以它看起来像Lisp。同样的算法是有点人为:
前面加上分隔字符串的开头
",1,2,-5,-23,15"
生成所有的尾巴
[",1,2,-5,-23,15", "1,2,-5,-23,15", ",2,-5,-23,15", .... ]
过滤器的列表,只留下与分隔符开头的字符串
[",1,2,-5,-23,15", ",2,-5,-23,15", .... ]
放下第一个分隔符并采用符号,直到达到下一个分隔符
["1", "2", .... ]
所以问题是:
我怎样才能改善功能splitByDelimiter
?
我可以删除前缀和删除分隔符并直接拆分字符串吗?
如何重写函数以减少括号?
可能我错过了一些东西,并且已经有了这个功能的标准功能?
是不是Data.List.Split.splitOn这样做?
鉴于此包不是基本安装(Haskell平台),我认为它容易被忽视。 – 2010-12-21 21:27:48
谢谢。它完全符合我的需求。 – sign 2010-12-21 21:33:12
这是一个黑客,但它,它的作品。
yourFunc str = map (+1) $ read ("[" ++ str ++ "]")
下面是使用unfoldr
非破解版:
import Data.List
import Control.Arrow(second)
-- break' is like break but removes the
-- delimiter from the rest string
break' d = second (drop 1) . break d
split :: String -> Maybe (String,String)
split [] = Nothing
split xs = Just . break' (==',') $ xs
yourFunc :: String -> [Int]
yourFunc = map ((+1) . read) . unfoldr split
谢谢。这是一个很好的观点。我喜欢在这里使用不同的展示方式。 – sign 2010-12-21 22:19:19
这是应用HaskellElephant的回答原来的问题,有轻微的变化
splitByDelimiter :: Char -> String -> [String] splitByDelimiter = unfoldr . splitSingle splitSingle :: Char -> String -> Maybe (String,String) splitSingle _ [] = Nothing splitSingle delimiter xs = let (ys, zs) = break (== delimiter) xs in Just (ys, drop 1 zs)
凡功能splitSingle分裂名单在第一个分隔符的两个子串中。
例如: "1,2,-5,-23,15" -> Just ("1", "2,-5,-23,15")
只是为了好玩,这里是你如何创建一个简单的解析器使用秒差距:
module Main where
import Control.Applicative hiding (many)
import Text.Parsec
import Text.Parsec.String
line :: Parser [Int]
line = number `sepBy` (char ',' *> spaces)
number = read <$> many digit
一个优点是,它很容易地创建一个解析器是在什么灵活它将接受:
*Main Text.Parsec Text.Parsec.Token> :load "/home/mikste/programming/Temp.hs"
[1 of 1] Compiling Main (/home/mikste/programming/Temp.hs, interpreted)
Ok, modules loaded: Main.
*Main Text.Parsec Text.Parsec.Token> parse line "" "1, 2, 3"
Right [1,2,3]
*Main Text.Parsec Text.Parsec.Token> parse line "" "10,2703, 5, 3"
Right [10,2703,5,3]
*Main Text.Parsec Text.Parsec.Token>
splitBy delimiter = foldr f [[]]
where f c [email protected](x:xs) | c == delimiter = []:l
| otherwise = (c:x):xs
编辑:不是由原作者,但下面是一个更多(过分?)详细和灵活性较差的版本(具体到Char
/String
),以帮助澄清如何工作。使用上述版本是因为它适用于任何使用Eq
实例的类型列表。
splitBy :: Char -> String -> [String]
splitBy _ "" = [];
splitBy delimiterChar inputString = foldr f [""] inputString
where f :: Char -> [String] -> [String]
f currentChar [email protected](partialString:handledStrings)
| currentChar == delimiterChar = "":allStrings -- start a new partial string at the head of the list of all strings
| otherwise = (currentChar:partialString):handledStrings -- add the current char to the partial string
-- input: "a,b,c"
-- fold steps:
-- first step: 'c' -> [""] -> ["c"]
-- second step: ',' -> ["c"] -> ["","c"]
-- third step: 'b' -> ["","c"] -> ["b","c"]
-- fourth step: ',' -> ["b","c"] -> ["","b","c"]
-- fifth step: 'a' -> ["","b","c"] -> ["a","b","c"]
splitBy del str = helper del str []
where
helper _ [] acc = let acc0 = reverse acc in [acc0]
helper del (x:xs) acc
| x==del = let acc0 = reverse acc in acc0 : helper del xs []
| otherwise = let acc0 = x : acc in helper del xs acc0
此代码工作正常 用途: - 分裂 “你的字符串”[]与任何分隔符来替换 ''
split [] t = [t]
split (a:l) t = if a==',' then (t:split l []) else split l (t++[a])
import qualified Text.Regex as RegExp
myRegexSplit :: String -> String -> [String]
myRegexSplit regExp theString =
let result = RegExp.splitRegex (RegExp.mkRegex regExp) theString
in filter (not . null) result
-- using regex has the advantage of making it easy to use a regular
-- expression instead of only normal strings as delimiters.
-- the splitRegex function tends to return an array with an empty string
-- as the last element. So the filter takes it out
-- how to use in ghci to split a sentence
let timeParts = myRegexSplit " " "I love ponies a lot"
`foldr相似(++)[] `也被称为`concat`,`putStrLn。 show`也被称为`print`。另外,`n pat 2013-02-27 02:36:30
可能的重复[如何在Haskell中拆分字符串?](http://stackoverflow.com/questions/4978578/how-to-split-a-string-in-haskell) – 2014-07-02 15:39:42