¿Hay alguna función haskell para concatenar la lista con el separador?

131

¿Existe una función para concatenar elementos de una lista con un separador? Por ejemplo:

> foobar " " ["is","there","such","a","function","?"]
["is there such a function ?"]

Gracias por cualquier respuesta!

Fopa Léon Constantin
fuente
13
Sé que las respuestas de lmgtfy son malas, pero vale la pena señalar que una búsqueda de "Cadena -> [Cadena] -> Cadena" en hoogle obtiene exactamente lo que desea. haskell.org/hoogle
sigfpe
3
para unirte a espacios que también tienesunwords
epsilonhalbe
1
@sigfpe Comentario lateral: Tendría que buscar [String] -> String -> Stringen caso de que la otra forma no devuelva respuesta, ¿verdad?
Lay González
1
@ LayGonzález La búsqueda depende de las permutaciones. Por ejemplo, buscar [a] -> (a -> b) -> [b]retornos mapcomo primer resultado.
gallais

Respuestas:

228

Sí, hay :

Prelude> import Data.List
Prelude Data.List> intercalate " " ["is","there","such","a","function","?"]
"is there such a function ?"

intersperse es un poco más general:

Prelude> import Data.List
Prelude Data.List> concat (intersperse " " ["is","there","such","a","function","?"])
"is there such a function ?"

Además, para el caso específico en el que desea unirse con un carácter de espacio, hay unwords:

Prelude> unwords ["is","there","such","a","function","?"]
"is there such a function ?"

unlinesfunciona de manera similar, solo que las cadenas están implosionadas usando el carácter de nueva línea y que también se agrega un carácter de nueva línea al final. (Esto lo hace útil para serializar archivos de texto, que deben cumplir con el estándar POSIX con una nueva línea final)

Niklas B.
fuente
¿Puede algo de eso tratar con posibles cadenas vacías?
CMCDragonkai
3
@CMCDragonkai No estoy seguro de a qué se refiere exactamente, pero sí, todas estas funciones permiten cadenas arbitrarias como separador y elementos. Por ejemplo, intercalate "," ["some", "", "string"] = "some,,string"yintercalate "" ["foo", "bar"] = "foobar"
Niklas B.
3
unlinesagrega una nueva línea a cada línea, es decir unlines ["A", "B"] = "A\nB\n", no es lo mismo que intercalar.
Kathy Van Stone
@KathyVanStone Interesante, supongo que nunca lo intenté y solo asumí que funciona de manera análoga unwords.
Niklas B.
1
Es bueno que haya algunas funciones normales de manipulación de cadenas y listas en la biblioteca estándar, y es bueno que publiques un ejemplo aquí, porque es bastante difícil encontrar documentación para este tipo de programación diaria en Haskell.
Andrew Koster
4

No es difícil escribir una línea usando foldr

join sep xs = foldr (\a b-> a ++ if b=="" then b else sep ++ b) "" xs
join " " ["is","there","such","a","function","?"]
Ilya Kharlamov
fuente
3
Sería beneficioso agregar una descripción a esto; alguien lo marcó como de baja calidad.
Arya McCarthy
3
joinBy sep cont = drop (length sep) $ concat $ map (\w -> sep ++ w) cont
Alaya
fuente
3

Algunas otras ideas de implementaciones de intercalar e intercalar, si alguien está interesado:

myIntersperse :: a -> [a] -> [a]
myIntersperse _ [] = []
myIntersperse e xs = init $ xs >>= (:[e])

myIntercalate :: [a] -> [[a]] -> [a]
myIntercalate e xs = concat $ myIntersperse e xs

xs >>= fes equivalente a concat (map f xs).

Alexis
fuente
2

Si desea escribir sus propias versiones de intercalatey intersperse:

intercalate :: [a] -> [[a]] -> [a]
intercalate s [] = []
intercalate s [x] = x
intercalate s (x:xs) = x ++ s ++ (intercalate s xs)

intersperse :: a -> [a] -> [a]
intersperse s [] = []
intersperse s [x] = [x]
intersperse s (x:xs) = x : s : (intersperse s xs)
Zoey Hewll
fuente
1
¿Por qué limitarse a las cuerdas? Además, sus padres alrededor de la aplicación de funciones son redundantes.
melpomene
Es cierto, intersperseno tiene que ser Strings, pero intercalatetendría que ser por lo menos Show, y si se hizo uso Show, que había necesidad de una cierta manera de tratar con ellos usando Strings de todos modos. Todavía me estoy acostumbrando a cómo Haskell se ocupa de las funciones / operadores mixtos de infijo y prefijo, y prefiero poner entre paréntesis cuando mezclo en caso de que termine con ganas de usarlo$
Zoey Hewll
intercalate :: [a] -> [[a]] -> [a]- por que Show? En cuanto a la sintaxis, Haskell no tiene ningún operador de prefijo (excepto -, que es una abominación), y la aplicación de función se ajusta más que cualquier operador de infijo: x:s:intersperse s xsestá bien (pero se lee mucho mejor si pone los espacios en: x : s : intersperse s xs(No Realmente no entiendo por qué a la gente le gusta dejar los espacios a su alrededor :)).
melpomene
Correcto. Siempre olvido que trabajar con cadenas es solo trabajar con listas. Showfue porque estaba asumiendo que querrías que el resultado fuera a String. Por "funciones / operadores de infijo y prefijo" quise decir "funciones de prefijo y operadores de infijo", pero eso no estaba claro. Unario -es la muerte. En cuanto a los :operadores infix y otros, si uso espacios depende en gran medida del contexto, pero siempre soy localmente coherente. por ejemplo, (:)en una coincidencia de patrones nunca tiene espacios, pero en otros lugares depende de si está entre corchetes y de mi estado de ánimo.
Zoey Hewll