如何在Haskell中拆分字符串?

Eri*_*son 154 string haskell

是否有一种在Haskell中拆分字符串的标准方法?

lineswords上一个空格或换行从拆分工作的伟大,但肯定没有拆就一个逗号一个标准的方式?

我在Hoogle上找不到它.

具体来说,我正在寻找split "," "my,comma,separated,list"回报的东西["my","comma","separated","list"].

Ste*_*eve 160

请记住,您可以查找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'
Run Code Online (Sandbox Code Playgroud)

因此,将其更改为带谓词的函数:

wordsWhen     :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
                      "" -> []
                      s' -> w : wordsWhen p s''
                            where (w, s'') = break p s'
Run Code Online (Sandbox Code Playgroud)

然后用你想要的任何谓词来调用它!

main = print $ wordsWhen (==',') "break,this,string,at,commas"
Run Code Online (Sandbox Code Playgroud)


Jon*_*FTW 125

有一个称为拆分的包.

cabal install split
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

ghci> import Data.List.Split
ghci> splitOn "," "my,comma,separated,list"
["my","comma","separated","list"]
Run Code Online (Sandbox Code Playgroud)

它带有许多其他功能,用于拆分匹配的分隔符或具有多个分隔符.

  • 自最近发布以来,拆分包现在是haskell平台的一部分. (34认同)
  • 导入Data.List.Split(splitOn)并转到城镇.splitOn :: Eq a => [a] - > [a] - > [[a]] (12认同)
  • 导入Data.List.Split不起作用 (9认同)
  • 凉.我不知道这个包裹.这是*终极拆分包,因为它可以很好地控制操作(在结果中修剪空间,在结果中保留分隔符,删除连续的分隔符等等).拆分列表有很多种方法,单个`split`函数不可能满足每个需求,你真的需要那种包. (8认同)
  • @RussAbbott,当您下载它时,分割包包含在Haskell Platform中(https://www.haskell.org/platform/contents.html),但在构建项目时不会自动加载。将 `split` 添加到 cabal 文件中的 `build-depends` 列表中,例如,如果您的项目名为 hello,则在 `executable hello` 行下方的 `hello.cabal` 文件中添加一行,如 ` build-depends: base, split`(注意两个空格缩进)。然后使用“cabal build”命令进行构建。比照。https://www.haskell.org/cabal/users-guide/developing-packages.html#example-a-package-containing-executable-programs (2认同)

Emm*_*ery 28

如果您使用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")
Run Code Online (Sandbox Code Playgroud)

要么:

{-# LANGUAGE OverloadedStrings #-}

import qualified Data.Text as T
main = print $ T.splitOn " " "this is a test"
Run Code Online (Sandbox Code Playgroud)

  • @RussAbbott 可能您需要依赖于 `text` 包或安装它。将属于另一个问题。 (2认同)
  • 无法将类型“T.Text”与“Char”匹配预期类型:[Char] 实际类型:[T.Text] (2认同)

evi*_*bag 18

在模块Text.Regex(Haskell平台的一部分)中,有一个函数:

splitRegex :: Regex -> String -> [String]
Run Code Online (Sandbox Code Playgroud)

它根据正则表达式拆分字符串.该API可以在Hackage中找到.

  • `找不到模块'Text.Regex'也许您的意思是Text.Read(来自base-4.10.1.0)` (3认同)

fuz*_*fuz 14

试试这个:

import Data.List (unfoldr)

separateBy :: Eq a => a -> [a] -> [[a]]
separateBy chr = unfoldr sep where
  sep [] = Nothing
  sep l  = Just . fmap (drop 1) . break (== chr) $ l
Run Code Online (Sandbox Code Playgroud)

仅适用于单个字符,但应易于扩展.


ant*_*ter 14

使用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]
Run Code Online (Sandbox Code Playgroud)

  • 导入Data.List.Split不起作用 (7认同)

Fra*_*ert 9

split :: Eq a => a -> [a] -> [[a]]
split d [] = []
split d s = x : split d (drop 1 y) where (x,y) = span (/= d) s
Run Code Online (Sandbox Code Playgroud)

例如

split ';' "a;bb;ccc;;d"
> ["a","bb","ccc","","d"]
Run Code Online (Sandbox Code Playgroud)

将删除单个尾随分隔符:

split ';' "a;bb;ccc;;d;"
> ["a","bb","ccc","","d"]
Run Code Online (Sandbox Code Playgroud)


fp_*_*ora 7

在不导入任何字符的情况下,无需将一个字符直接替换为空格,words而是将目标分隔符作为空格。就像是:

words [if c == ',' then ' ' else c|c <- "my,comma,separated,list"]
Run Code Online (Sandbox Code Playgroud)

要么

words let f ',' = ' '; f c = c in map f "my,comma,separated,list"
Run Code Online (Sandbox Code Playgroud)

您可以使它成为带有参数的函数。您可以消除匹配多个字符的参数,例如:

 [if elem c ";,.:-+@!$#?" then ' ' else c|c <-"my,comma;separated!list"]
Run Code Online (Sandbox Code Playgroud)


Rob*_*bie 6

我昨天开始学习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)
Run Code Online (Sandbox Code Playgroud)

得到:

*Main> split ' ' "this is a test"
["this","is","a","test"]
Run Code Online (Sandbox Code Playgroud)

或许你想要

*Main> splitWithStr  " and " "this and is and a and test"
["this","is","a","test"]
Run Code Online (Sandbox Code Playgroud)

这将是:

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)
Run Code Online (Sandbox Code Playgroud)

  • 你在六月写了这篇文章,所以我假设你已经开始了你的旅程:)作为一个练习,尝试重写这个函数而没有反向或长度,因为使用这些函数会导致算法复杂性的损失并且还会阻止应用程序进入无限列表.玩得开心! (3认同)

mxs*_*mxs 6

我觉得这更容易理解:

split :: Char -> String -> [String]
split c xs = case break (==c) xs of 
  (ls, "") -> [ls]
  (ls, x:rs) -> ls : split c rs
Run Code Online (Sandbox Code Playgroud)


Evi*_*ine 5

我不知道如何在Steve的答案中添加评论,但我想推荐
  GHC库文档,
特别是
  Data.List中的Sublist函数.

作为参考,这比阅读简单的Haskell报告要好得多.

通常,关于何时创建新的子列表以供应的规则的折叠也应该解决它.