numero multiplos listas leer impresion ejercicios ejemplos como basico string haskell

string - listas - multiplos en haskell



¿Cómo dividir una cadena en Haskell? (12)

¿Hay una forma estándar de dividir una cadena en Haskell?

lines y las words funcionan bien si se dividen en un espacio o línea nueva, pero seguramente hay una forma estándar de dividir en una coma. No pude encontrarlo en Hoogle?

Para ser específico, estoy buscando algo donde split "," "my,comma,separated,list" devuelve ["my","comma","separated","list"]

Gracias.


¡Recuerde que puede buscar la definición de funciones de Prelude!

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

Mirando allí, la definición de words es,

words :: String -> [String] words s = case dropWhile Char.isSpace s of "" -> [] s'' -> w : words s'''' where (w, s'''') = break Char.isSpace s''

Por lo tanto, cámbielo por una función que tenga un predicado:

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

¡Entonces llámalo con el predicado que quieras!

main = print $ wordsWhen (=='','') "break,this,string,at,commas"


Además de las funciones eficientes y preconstruidas dadas en las respuestas, agregaré las mías que son simplemente parte de mi repertorio de funciones de Haskell que estaba escribiendo para aprender el idioma en mi propio tiempo:

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

Las soluciones son al menos recursivas de cola para que no incurran en un desbordamiento de pila.


Ejemplo en el ghci:

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


Empecé a aprender Haskell ayer, así que corrígeme si estoy equivocado pero:

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)

da:

*Main> split '' '' "this is a test" ["this","is","a","test"]

o tal vez querías

*Main> splitWithStr " and " "this and is and a and test" ["this","is","a","test"]

cuál podría ser:

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)


En el módulo Text.Regex (parte de la Plataforma Haskell), hay una función:

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

que divide una cadena basada en una expresión regular. La API se puede encontrar en Hackage .


Hay un paquete para esto llamado split .

cabal install split

Úselo así:

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

Viene con muchas otras funciones para dividir en delimitadores coincidentes o tener varios delimitadores.


No sé cómo agregar un comentario en la respuesta de Steve, pero me gustaría recomendar el
Documentación de las bibliotecas de GHC
y allí específicamente el
Funciones de sublista en Data.List

Lo cual es mucho mejor como referencia, que solo leer el informe simple de Haskell.

Genéricamente, un fold con una regla sobre cuándo crear una nueva sublista para alimentar, debería resolverlo también.


Prueba este:

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

Solo funciona para un solo char, pero debe poder extenderse fácilmente.



Sin importar nada una sustitución directa de un carácter por un espacio, el separador de destino para words es un espacio. Algo como:

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

o

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

Puede convertir esto en una función con parámetros. Puedes eliminar el parámetro carácter a coincidencia mis muchos coincidentes, como en:

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


Use Data.List.Split , que usa 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]


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

P.ej

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

Se eliminará un único delimitador final:

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