Answers:
有一个名为split的软件包。
cabal install split
像这样使用它:
ghci> import Data.List.Split
ghci> splitOn "," "my,comma,separated,list"
["my","comma","separated","list"]
它带有许多其他功能,用于在匹配的定界符上分割或具有多个定界符。
split
功能可以满足所有需求,您确实需要那种包装。
split
到build-depends
清单文件中,然后在hello.cabal
该executable hello
行下面的文件中,添加类似于build-depends:base,split之类的行(请注意两个空格缩进)。然后使用cabal build
命令进行构建。cf. haskell.org/cabal/users-guide/…–
请记住,您可以查找Prelude函数的定义!
http://www.haskell.org/onlinereport/standard-prelude.html
看那里的定义words
是,
words :: String -> [String]
words s = case dropWhile Char.isSpace s of
"" -> []
s' -> w : words s''
where (w, s'') = break Char.isSpace s'
因此,将其更改为带有谓词的函数:
wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s = case dropWhile p s of
"" -> []
s' -> w : wordsWhen p s''
where (w, s'') = break p s'
然后用您想要的谓词调用它!
main = print $ wordsWhen (==',') "break,this,string,at,commas"
如果使用Data.Text,则存在splitOn:
http://hackage.haskell.org/packages/archive/text/0.11.2.0/doc/html/Data-Text.html#v:splitOn
这是在Haskell平台中构建的。
因此,例如:
import qualified Data.Text as T
main = print $ T.splitOn (T.pack " ") (T.pack "this is a test")
要么:
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.Text as T
main = print $ T.splitOn " " "this is a test"
text
软件包或进行安装。虽然会属于另一个问题。
在Text.Regex模块(Haskell平台的一部分)中,有一个函数:
splitRegex :: Regex -> String -> [String]
根据正则表达式分割字符串。该API可以在Hackage中找到。
Could not find module ‘Text.Regex’ Perhaps you meant Text.Read (from base-4.10.1.0)
使用Data.List.Split
,它使用split
:
[me@localhost]$ ghci
Prelude> import Data.List.Split
Prelude Data.List.Split> let l = splitOn "," "1,2,3,4"
Prelude Data.List.Split> :t l
l :: [[Char]]
Prelude Data.List.Split> l
["1","2","3","4"]
Prelude Data.List.Split> let { convert :: [String] -> [Integer]; convert = map read }
Prelude Data.List.Split> let l2 = convert l
Prelude Data.List.Split> :t l2
l2 :: [Integer]
Prelude Data.List.Split> l2
[1,2,3,4]
在不导入任何字符的情况下,无需将一个字符直接替换为空格,目标分隔符为words
空格。就像是:
words [if c == ',' then ' ' else c|c <- "my,comma,separated,list"]
要么
words let f ',' = ' '; f c = c in map f "my,comma,separated,list"
您可以使它成为带有参数的函数。您可以消除匹配多个字符的参数,例如:
[if elem c ";,.:-+@!$#?" then ' ' else c|c <-"my,comma;separated!list"]
我昨天开始学习Haskell,所以如果我错了,请纠正我,但是:
split :: Eq a => a -> [a] -> [[a]]
split x y = func x y [[]]
where
func x [] z = reverse $ map (reverse) z
func x (y:ys) (z:zs) = if y==x then
func x ys ([]:(z:zs))
else
func x ys ((y:z):zs)
给出:
*Main> split ' ' "this is a test"
["this","is","a","test"]
也许你想要
*Main> splitWithStr " and " "this and is and a and test"
["this","is","a","test"]
可能是:
splitWithStr :: Eq a => [a] -> [a] -> [[a]]
splitWithStr x y = func x y [[]]
where
func x [] z = reverse $ map (reverse) z
func x (y:ys) (z:zs) = if (take (length x) (y:ys)) == x then
func x (drop (length x) (y:ys)) ([]:(z:zs))
else
func x ys ((y:z):zs)
split
,被语言完善的库所破坏。但是还是谢谢你。
我不知道如何在Steve的答案上添加注释,但是我想推荐
GHC库文档,
特别是
在Data.List中的Sublist函数中。
作为参考,比仅阅读简单的Haskell报告要好得多。
通常,对何时创建新的子列表进行馈送的规则的折叠也应该解决。
除了答案中给出的高效和预先构建的函数外,我还将添加自己的函数,这些都是我自己编写的用于学习语言的Haskell函数库的一部分:
-- Correct but inefficient implementation
wordsBy :: String -> Char -> [String]
wordsBy s c = reverse (go s []) where
go s' ws = case (dropWhile (\c' -> c' == c) s') of
"" -> ws
rem -> go ((dropWhile (\c' -> c' /= c) rem)) ((takeWhile (\c' -> c' /= c) rem) : ws)
-- Breaks up by predicate function to allow for more complex conditions (\c -> c == ',' || c == ';')
wordsByF :: String -> (Char -> Bool) -> [String]
wordsByF s f = reverse (go s []) where
go s' ws = case ((dropWhile (\c' -> f c')) s') of
"" -> ws
rem -> go ((dropWhile (\c' -> (f c') == False)) rem) (((takeWhile (\c' -> (f c') == False)) rem) : ws)
这些解决方案至少是尾部递归的,因此它们不会引起堆栈溢出。
ghci中的示例:
> import qualified Text.Regex as R
> R.splitRegex (R.mkRegex "x") "2x3x777"
> ["2","3","777"]
ghci
?
Data.List
甚至发布的版本中提供这样的功能Prelude
。如果无法用于代码高尔夫,那么它是如此常见且令人讨厌。