Existe alguma função haskell para concatenar a lista com o separador?

131

Existe uma função para concatenar elementos de uma lista com um separador? Por exemplo:

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

Obrigado por qualquer resposta!

Fopa Léon Constantin
fonte
13
Sei que as respostas lmgtfy são ruins, mas vale a pena notar que uma pesquisa por "String -> [String] -> String" no hoogle obtém exatamente o que você deseja. haskell.org/hoogle
SIGFPE
3
por se juntar com espaços você também temunwords
epsilonhalbe
1
Comentário do @sigfpe Side: Você teria que procurar [String] -> String -> Stringcaso o outro caminho não retornasse resposta, certo?
Lay González
1
@ LayGonzález A pesquisa está sujeita a permutações. Por exemplo, procurando [a] -> (a -> b) -> [b]retornos mapcomo seu primeiro resultado.
Gallais

Respostas:

227

Sim, existe :

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

intersperse é um pouco mais geral:

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

Além disso, para o caso específico em que você deseja ingressar com um caractere de espaço, existe unwords:

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

unlinesfunciona da mesma forma, apenas que as seqüências de caracteres são implodidas usando o caractere de nova linha e que um caractere de nova linha também é adicionado ao final. (Isso o torna útil para serializar arquivos de texto, que devem ser finalizados pelo padrão POSIX com uma nova linha à direita)

Niklas B.
fonte
Alguma coisa pode lidar com possíveis sequências vazias?
CMCDragonkai
3
@CMCDragonkai Não tenho certeza do que exatamente você está se referindo, mas sim, todas essas funções permitem seqüências arbitrárias como separador e elementos. Por exemplo, intercalate "," ["some", "", "string"] = "some,,string"eintercalate "" ["foo", "bar"] = "foobar"
Niklas B. 23/06
3
unlinesadiciona uma nova linha a cada linha, ou seja unlines ["A", "B"] = "A\nB\n", não é o mesmo que intercalar.
Kathy Van Stone
@KathyVanStone Interessante, acho que nunca tentei e só assumi que funciona de forma análoga unwords.
Niklas B.
1
É bom que haja algumas funções normais de manipulação de strings e listas na biblioteca padrão, e é bom que você esteja postando um exemplo aqui, porque é muito difícil encontrar qualquer documentação para esse tipo de programação cotidiana no Haskell.
Andrew Koster
4

Não é difícil escrever uma linha 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
fonte
3
Seria benéfico adicionar uma descrição a isso; alguém sinalizou isso como de baixa qualidade.
Arya McCarthy
3
joinBy sep cont = drop (length sep) $ concat $ map (\w -> sep ++ w) cont
Alaya
fonte
3

Algumas outras idéias de implementações de intercalar e intercalar, se alguém estiver interessado:

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

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

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

Alexis
fonte
2

Se você queria escrever suas próprias versões intercalatee 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
fonte
1
Por que limitar-se a strings? Além disso, seus parênteses em torno do aplicativo de função são redundantes.
Melpomene
É verdade, interspersenão precisa ser Strings, mas intercalateseria necessário, pelo menos, ser Show, e se você fez uso Show, você precisa de alguma maneira de lidar com eles usando Strings de qualquer maneira. Eu ainda estou me acostumando à forma como Haskell lida com mistos infixas e prefixo funções / operadores, e eu prefiro Bracketing quando a mistura no caso de eu acabar querendo uso$
Zoey Hewll
intercalate :: [a] -> [[a]] -> [a]porque Show? Quanto à sintaxe, Haskell não possui nenhum operador de prefixo (exceto -, que é uma abominação), e o aplicativo de função se liga mais firmemente que qualquer operador de infixo: x:s:intersperse s xsé bom (mas fica muito melhor se você colocar os espaços em: x : s : intersperse s xs(eu não realmente não entendo por que as pessoas gostam de deixar de fora os espaços ao redor :)).
Melpomene
Certo. Eu continuo esquecendo que trabalhar com strings é apenas trabalhar com listas. Showfoi porque eu estava assumindo que você gostaria que o resultado fosse um String. Por "funções / operadores de infixo e prefixo", quis dizer "funções de prefixo e operadores de infixo", mas isso não estava claro. Unário -é morte. Quanto aos :operadores de infix e outros, o uso de espaços depende muito do contexto, mas sempre sou consistente localmente. por exemplo, (:)em uma correspondência de padrões nunca há espaços, mas em outros lugares depende se está entre colchetes e no meu humor.
Zoey Hewll