development

하스켈에서 줄을 나누는 방법?

big-blog 2020. 6. 12. 08:18
반응형

하스켈에서 줄을 나누는 방법?


Haskell에서 문자열을 분리하는 표준 방법이 있습니까?

lineswords업무 공백이나 줄 바꿈에 분할에서 큰하지만 반드시 쉼표에 분할하는 표준 방법은 무엇입니까?

Hoogle에서 찾을 수 없습니다.

구체적으로, split "," "my,comma,separated,list"returns 가있는 곳을 찾고 ["my","comma","separated","list"]있습니다.


이를위한 split 패키지가 있습니다 .

cabal install split

다음과 같이 사용하십시오.

ghci> import Data.List.Split
ghci> splitOn "," "my,comma,separated,list"
["my","comma","separated","list"]

일치하는 구분 기호를 분할하거나 여러 구분 기호를 갖는 많은 다른 기능이 제공됩니다.


Prelude 기능의 정의를 찾을 수 있습니다!

http://www.haskell.org/onlinereport/standard-prelude.html

거기를 보면 wordsis 의 정의

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.Regex (Haskell 플랫폼의 일부) 모듈에는 다음과 같은 기능이 있습니다.

splitRegex :: Regex -> String -> [String]

정규식을 기반으로 문자열을 분할합니다. API는 Hackage 에서 찾을 수 있습니다 .


를 사용 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]

이거 한번 해봐:

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

단일 문자에서만 작동하지만 쉽게 확장 가능해야합니다.


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

예 :

split ';' "a;bb;ccc;;d"
> ["a","bb","ccc","","d"]

단일 후행 구분 기호가 삭제됩니다.

split ';' "a;bb;ccc;;d;"
> ["a","bb","ccc","","d"]

나는 어제 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)

I don’t know how to add a comment onto Steve’s answer, but I would like to recommend the
  GHC libraries documentation,
and in there specifically the
  Sublist functions in Data.List

Which is much better as a reference, than just reading the plain Haskell report.

Generically, a fold with a rule on when to create a new sublist to feed, should solve it too.


Without importing anything a straight substitution of one character for a space, the target separator for words is a space. Something like:

words [if c == ',' then ' ' else c|c <- "my,comma,separated,list"]

or

words let f ',' = ' '; f c = c in map f "my,comma,separated,list"

You can make this into a function with parameters. You can eliminate the parameter character-to-match my matching many, like in:

 [if elem c ";,.:-+@!$#?" then ' ' else c|c <-"my,comma;separated!list"]

In addition to the efficient and pre-built functions given in answers I'll add my own which are simply part of my repertory of Haskell functions I was writing to learn the language on my own time:

-- 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)

The solutions are at least tail-recursive so they won't incur a stack overflow.


Example in the ghci:

>  import qualified Text.Regex as R
>  R.splitRegex (R.mkRegex "x") "2x3x777"
>  ["2","3","777"]

참고URL : https://stackoverflow.com/questions/4978578/how-to-split-a-string-in-haskell

반응형