Esiste una funzione haskell per concatenare l'elenco con il separatore?


131

Esiste una funzione per concatenare elementi di un elenco con un separatore? Per esempio:

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

Grazie per qualsiasi risposta!


13
So che le risposte di lmgtfy sono sbagliate, ma vale la pena notare che la ricerca di "String -> [String] -> String" su hoogle ottiene esattamente quello che vuoi. haskell.org/hoogle
sigfpe

3
per unwords
unirti

1
@sigfpe Commento laterale: dovresti cercare [String] -> String -> Stringnel caso in cui l'altro modo non restituisca risposta, giusto?
Lay González

1
@ LayGonzález La ricerca dipende dalle permutazioni. Ad esempio, la ricerca di [a] -> (a -> b) -> [b]resi mapcome primo risultato.
gallais,

Risposte:


228

Sì, c'è :

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

intersperse è un po 'più generale:

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

Inoltre, per il caso specifico in cui si desidera unirsi a un carattere spazio, esiste unwords:

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

unlinesfunziona in modo simile, solo che le stringhe sono implose usando il carattere di nuova riga e che alla fine viene aggiunto anche un carattere di nuova riga. (Ciò lo rende utile per serializzare i file di testo, che devono terminare per POSIX standard con una nuova riga finale)


Qualcuno può occuparsi di possibili stringhe vuote?
CMCDragonkai,

3
@CMCDragonkai Non sono sicuro di cosa ti riferisca esattamente, ma sì, tutte queste funzioni consentono stringhe arbitrarie sia come separatore che come elementi. Ad esempio, intercalate "," ["some", "", "string"] = "some,,string"eintercalate "" ["foo", "bar"] = "foobar"
Niklas B.

3
unlinesaggiunge una nuova riga a ciascuna riga, ovvero unlines ["A", "B"] = "A\nB\n"non è la stessa di intercalare.
Kathy Van Stone,

@KathyVanStone Interessante, suppongo di non aver mai provato e ho solo pensato che funzionasse in modo analogo unwords.
Niklas B.

1
È bello che ci siano alcune normali funzioni di manipolazione di stringhe ed elenchi nella libreria standard, ed è bello che tu pubblichi un esempio qui, perché è abbastanza difficile trovare documentazione per questo tipo di programmazione quotidiana in Haskell.
Andrew Koster,

4

Non è difficile scrivere una riga usando foldr

join sep xs = foldr (\a b-> a ++ if b=="" then b else sep ++ b) "" xs
join " " ["is","there","such","a","function","?"]

3
Sarebbe utile aggiungere una descrizione a questo; qualcuno lo ha contrassegnato come di bassa qualità.
Arya McCarthy,

3
joinBy sep cont = drop (length sep) $ concat $ map (\w -> sep ++ w) cont

3

Alcune altre idee di implementazioni di intersperse e intercalate, se qualcuno è interessato:

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


2

Se si desidera scrivere le proprie versioni di 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)

1
Perché limitarti alle stringhe? Inoltre, le parentesi attorno all'applicazione della funzione sono ridondanti.
melpomene,

È vero, interspersenon deve essere Strings, ma intercalateavrebbe bisogno di almeno essere Show, e se ha fatto uso Show, avresti bisogno di qualche modo per trattare con loro utilizzando Strings comunque. Mi sto ancora abituando al modo in cui Haskell gestisce le funzioni / gli operatori di infissi e prefissi misti, e preferisco il bracketing durante il mixaggio nel caso in cui $
finissi

intercalate :: [a] -> [[a]] -> [a]- perché Show? Per quanto riguarda la sintassi, Haskell non ha alcun operatore prefisso (tranne -che, che è un abominio), e l'applicazione della funzione si lega più strettamente di qualsiasi operatore infisso: x:s:intersperse s xsva bene (ma legge molto meglio se metti gli spazi in: x : s : intersperse s xs(Io don capisco davvero perché alla gente piace lasciare gli spazi intorno :)).
melpomene,

Destra. Continuo a dimenticare che lavorare con le stringhe funziona solo con le liste. Showera perché pensavo che avresti voluto che il risultato fosse a String. Con "funzioni / operatori di prefisso e prefisso" intendevo "funzioni di prefisso e operatori di infisso", ma non era chiaro. Unario -è la morte. Per quanto riguarda gli :operatori s e altri operatori infix, il fatto che io usi gli spazi dipende fortemente dal contesto, ma sono sempre coerente a livello locale. ad esempio, (:)in un pattern match non ci sono mai spazi, ma altrove dipende dal fatto che sia tra parentesi e dal mio umore.
Zoey Hewll
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.