No se puede encontrar la manera de fusionar dos listas de la siguiente manera en Haskell:La fusión de dos listas en Haskell
INPUT: [1,2,3,4,5] [11,12,13,14]
OUTPUT: [1,11,2,12,3,13,4,14,5]
No se puede encontrar la manera de fusionar dos listas de la siguiente manera en Haskell:La fusión de dos listas en Haskell
INPUT: [1,2,3,4,5] [11,12,13,14]
OUTPUT: [1,11,2,12,3,13,4,14,5]
merge :: [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = x : y : merge xs ys
Soy nuevo en la programación funcional, y el código me hace preguntarme esto: ¿se aplica la optimización de la cola de llamadas en ese forma de recursión también? –
No, no es así. La llamada final es (:), y no necesita optimización. – Ingo
Hay una versión más lenta de esto en [otra respuesta] (http://stackoverflow.com/a/3987188/2157640). Es flojo en el segundo parámetro. – Palec
EDIT: Tome un vistazo a los comentarios de respuesta y Ed'ka !
Otra posibilidad:
merge xs ys = concatMap (\(x,y) -> [x,y]) (zip xs ys)
O, si te gusta Aplicativo:
merge xs ys = concat $ getZipList $ (\x y -> [x,y]) <$> ZipList xs <*> ZipList ys
Sí, mal, eso solo funciona en listas de igual longitud. – bogatyrjov
Entonces, ¿por qué cree que sencilla (. Concat transponer) "no es lo suficientemente bonita"? Asumo que has probado algo como:
merge :: [[a]] -> [a]
merge = concat . transpose
merge2 :: [a] -> [a] -> [a]
merge2 l r = merge [l,r]
De este modo se puede evitar una recursión explícita (vs la primera respuesta) y todavía es más simple que la segunda respuesta. ¿Cuáles son los inconvenientes?
Ah, me olvidé de la transposición, y me perdí el comentario. Muy bien, +1 (Pero no necesariamente diría que es mucho más fácil que mi primera solución.) – danlei
De acuerdo. Su solución probablemente sea aún más sencilla. Sin embargo, el verdadero problema es que no es 100% correcta: para las listas de diferentes longitudes (como en la entrada de muestra de la pregunta) no funciona como se esperaba (seguimiento '5' falta). –
¡Buena captura! Pasé por alto el 5 en la salida de muestra. Actualizaré mi respuesta con un puntero a su respuesta y comentarios. ¡Gracias! – danlei
quiero proponer una versión más perezoso de fusión:
merge [] ys = ys
merge (x:xs) ys = x:merge ys xs
Para un caso de ejemplo, el uso se puede comprobar una reciente Así que la pregunta acerca lazy generation of combinations.
La versión en la respuesta aceptada es innecesariamente estricta en el segundo argumento y eso es lo que se mejora aquí.
Bueno, eso pone todos los elementos de ys al final, por lo que no funciona. Pero creo que lo que querías decir es invertir el orden de las dos primeras ecuaciones en la solución de andri. – Yitz
No, hace lo mismo: alterna entre cada lista. Observe que 'xs' y' ys' se intercambian en la llamada recursiva. –
¡Es una gran solución! Ojalá pudiera pensar en algo así yo mismo – bogatyrjov
-- ++
pp [] [] = []
pp [] (h:t) = h:pp [] t
pp (h:t) [] = h:pp t []
pp (h:t) (a:b) = h : pp t (a:b)
Esta solución es incorrecta. La línea final debe ser 'pp (h: t) (a: b) = h: a: pp t b'. – bisserlis
Sin duda, un caso para un Despliegue:
interleave :: [a] -> [a] -> [a]
interleave = curry $ unfoldr g
where
g ([], []) = Nothing
g ([], (y:ys)) = Just (y, (ys, []))
g (x:xs, ys) = Just (x, (ys, xs))
Tu código original no funcionó; 'interleave [] [1,2,3]' daría '[]'. Creo que debería funcionar ahora. – dfeuer
otro caso para su apomorfismo ['unfoldr''] (http://stackoverflow.com/q/24519530/849891)! (Entonces será equivalente a [esta respuesta] (http://stackoverflow.com/a/3987188/849891) arriba). –
@dfeuer (el comentario anterior) –
Por lo general, a aprender más si se le explica lo que ha intentado y por qué no funcionó, de esa manera la gente puede hacer algo de relleno-en-el brechas en lugar de solo darte un pedazo de código. –
Relacionados: [Lista de listas de intercalación en Haskell] (http://stackoverflow.com/q/14186433/2157640) – Palec