2010-01-24 14 views
5

¿Cómo puedo escribir una función en Haskell, que toma una cadena de entrada en el formato a1a2a3 y se expande en a1a2a2a3a3a3. Por ejemplo, la cadena de entrada "código" se expandiría a "coodddeeee"Learning Haskell: Pregunta de manipulación de cadenas

+0

Por favor enviar el código que ha escrito para resolver esto hasta ahora. De lo contrario, la gente puede sospechar que esto es tarea. –

+0

Te lo aseguro, esto no es tarea :) Estuve trabajando a través de los ejercicios en un libro de Haskell y mi cerebro se congeló por esto. Todo lo que sé en este punto es que necesitaré usar el operador ++, algún tipo de manipulación de matriz y posible uso de la función de longitud –

Respuesta

9

Probablemente muy ineficiente :)

f :: Int -> [Char] -> [Char] 
f _ [] = [] 
f n (c:s) = (replicate n c) ++ (f (n+1) s) 

g :: [Char] -> [Char] 
g s = f 1 s 

.

*Main> g "code" 
"coodddeeee" 
+5

FYI: la yuxtaposición se une más firmemente que cualquier otra cosa excepto @, por lo que puedes eliminar algunos paréntesis excesivamente paranoicos. f n (c: s) = replicar n C++ f (n + 1) s –

19

Así que desea que el nth repita n veces.

f :: String -> String 
f x = concatMap g (zip x [1..]) 
    where 
     g (x,y) = replicate y x 

Estoy seguro de que hay una forma más fácil de hacerlo.

Explicación: Primero obtenemos la cadena y la emparejamos con su lugar en la lista (comenzando en 1). Esto es lo que hace postal:

Prelude> zip "code" [1..] 
[('c',1),('o',2),('d',3),('e',4)] 

Ahora la función g (x,y) utiliza la función de replicación que se replica lo que quiera y veces. Entonces replicamos x, y veces.

Prelude> g ('z',4) 
"zzzz" 

Si hacemos un mapa de esta función sobre la lista producida obtener el resultado:

Prelude> map g $ zip "code" [1..] 
["c","oo","ddd","eeee"] 

Si usted tiene una lista de cadenas, puede concatenar juntos usando concat. concatMap aplica la función g a cada par de letras y números y luego concatena la cadena en el resultado final.

Prelude> concat $ map g $ zip "code" [1..] 
"coodddeeee" 

Básicamente: concat $ map g ->concatMap g

EDIT: ahora funciona, sino que también se puede hacer de una línea así:

f x = concatMap (\(a,b)->replicate b a) $ zip x [1..] 

Salida:

Prelude> f "lambda" 
"laammmbbbbdddddaaaaaa" 
+0

Jonno ... ¿Podría explicar esa respuesta, como alguien que está en las primeras etapas de aprendiendo Haskell, la respuesta anterior simplemente no tiene sentido para mí. –

+0

Consulte la edición para obtener una explicación –

+2

Reemplazaré 'g' con' uncurry. flip replicate'. Hace lo mismo, pero usa funciones de biblioteca Haskell estándar. –

15
import Control.Monad 
f = zip [1..] >=> uncurry replicate 

produce

Main> f "code" 
"coodddeeee" 
+1

¡Agradable! Para aquellas personas como yo, que no conocen el tipo de operador: "Composición de mónadas de Kleisli de izquierda a derecha:' (> =>) :: Monad m => (a -> mb) -> (b -> mc) -> (a -> mc) '" –

1
Prelude> let l = "code" in concat $ [take y $ repeat (last $ take y l) | y <- [1..length l]] 
"coodddeeee" 
4

¿Por qué la gente odia las listas por comprensión?

Prelude> let f s = concat [ replicate x y | (x,y) <- zip [1..] s] 
Prelude> f "code" 
"coodddeeee" 

o si quiere volverse loco con extensiones

Prelude> :set -XParallelListComp 
Prelude> let f s = concat [ replicate x y | x <- [1..] | y <- s] 
Prelude> f "code" 
"coodddeeee" 
Cuestiones relacionadas