как разбить строку в haskell?

<p>есть ли стандартный способ разбить строку в haskell?</p><p><code>lines</code> и <code>words</code> отлично работают от разделения на пробел или символ новой строки, но наверняка есть стандартный способ разделения на запятую?</p><p>я не смог найти его в google.</p><p>чтобы быть конкретным, я ищу что-то, где <code>split "," "my,comma,separated,list"</code> возвращает <code>["my","comma","separated","list"]</code>.</p>

<p>для этого есть пакет <a href="https://hackage.haskell.org/package/split/docs/data-list-split.html">split</a> .</p><pre><code>cabal install split </code></pre><p>используйте это так:</p><pre><code>ghci> import data.list.split ghci> spliton "," "my,comma,separated,list" ["my","comma","separated","list"] </code></pre><p>он поставляется с множеством других функций для разделения на совпадающие разделители или с несколькими разделителями.</p>

<p>помните, что вы можете посмотреть определение функций prelude!</p><p> <a href="http://www.haskell.org/onlinereport/standard-prelude.html">http://www.haskell.org/onlinereport/standard-prelude.html</a> </p><p>глядя туда, определение <code>words</code> есть,</p><pre><code>words :: string -> [string] words s = case dropwhile char.isspace s of "" -> [] s' -> w : words s'' where (w, s'') = break char.isspace s' </code></pre><p>итак, измените его для функции, которая принимает предикат:</p><pre><code>wordswhen :: (char -> bool) -> string -> [string] wordswhen p s = case dropwhile p s of "" -> [] s' -> w : wordswhen p s'' where (w, s'') = break p s' </code></pre><p>тогда назовите это с любым предикатом, который вы хотите!</p><pre><code>main = print $ wordswhen (==',') "break,this,string,at,commas" 

если вы используете data.text, есть spliton: <a href="http://hackage.haskell.org/packages/archive/text/0.11.2.0/doc/html/data-text.html#v: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") </code></pre><p>или же:</p><pre><code>{-# language overloadedstrings #-} import qualified data.text as t main = print $ t.spliton " " "this is a test" 

в модуле text.regex (часть платформы haskell) есть функция:splitregex :: regex -> string -> [string] которая разбивает строку на основе регулярного выражения. api можно найти по адресу <a href="http://hackage.haskell.org/packages/archive/regex-compat/0.92/doc/html/text-regex.html">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] </code></pre>

<p>попробуй это:</p><pre><code>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) </code></pre><p>дает:</p><pre><code>*main> split ' ' "this is a test" ["this","is","a","test"] </code></pre><p>или, может быть, вы хотели</p><pre><code>*main> splitwithstr " and " "this and is and a and test" ["this","is","a","test"] </code></pre><p>который будет:</p><pre><code>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) 

я не знаю, как добавить комментарий к ответу стива, но я бы порекомендовал <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/index.html">документация библиотек ghc , и там конкретно <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base/data-list.html#g:10">функции подсписка в data.list что гораздо лучше в качестве справки, чем просто чтение простого отчета на haskell.как правило, ее следует решить также с помощью правила о том, когда создавать новый подсписок для подачи.

не импортируя ничего в качестве прямой замены одного символа на пробел, целевой разделитель для 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"] </code></pre>

<p>в дополнение к эффективным и предварительно созданным функциям, приведенным в ответах, я добавлю свои собственные, которые просто являются частью моего набора функций haskell, которые я писал для изучения языка в свое свободное время:</p><pre><code>-- 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) </code></pre><p>решения как минимум хвостовые рекурсивные, поэтому они не повлекут за собой переполнение стека.</p>

<p>пример в ghci:</p><pre><code>> import qualified text.regex as r > r.splitregex (r.mkregex "x") "2x3x777" > ["2","3","777"] </code></pre>