Gibt es eine Haskell-Funktion, um eine Liste mit einem Trennzeichen zu verketten?

131

Gibt es eine Funktion zum Verketten von Elementen einer Liste mit einem Trennzeichen? Beispielsweise:

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

Vielen Dank für jede Antwort!

Fopa Léon Constantin
quelle
13
Ich weiß, dass lmgtfy Antworten schlecht sind, aber es ist erwähnenswert, dass eine Suche nach "String -> [String] -> String" bei Google genau das bringt, was Sie wollen. haskell.org/hoogle
sigfpe
3
für die Verbindung mit Räumen haben Sie auchunwords
epsilonhalbe
1
@sigfpe Nebenbemerkung: Sie müssten suchen, [String] -> String -> Stringfalls der andere Weg keine Antwort liefert, oder?
Lay González
1
@ LayGonzález Die Suche hängt von den Permutationen ab. Zum Beispiel die Suche nach [a] -> (a -> b) -> [b]Rückgaben mapals erstes Ergebnis.
Gallais

Antworten:

227

Ja, es gibt :

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

intersperse ist etwas allgemeiner:

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

Für den speziellen Fall, in dem Sie sich mit einem Leerzeichen verbinden möchten, gibt es außerdem Folgendes unwords:

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

unlinesfunktioniert ähnlich, nur dass die Zeichenfolgen mit dem Zeilenumbruchzeichen implodiert werden und dass am Ende auch ein Zeilenumbruchzeichen hinzugefügt wird. (Dies macht es nützlich für die Serialisierung von Textdateien, die gemäß POSIX-Standard mit einem nachgestellten Zeilenumbruch enden müssen.)

Niklas B.
quelle
Kann irgendetwas davon mit möglichen leeren Strings umgehen?
CMCDragonkai
3
@CMCDragonkai Nicht sicher, worauf Sie sich genau beziehen, aber ja, diese Funktionen erlauben alle beliebige Zeichenfolgen als Trennzeichen und als Elemente. Zum Beispiel intercalate "," ["some", "", "string"] = "some,,string"undintercalate "" ["foo", "bar"] = "foobar"
Niklas B.
3
unlinesFügt jeder Zeile eine neue Zeile hinzu, das heißt unlines ["A", "B"] = "A\nB\n", es ist nicht dasselbe wie interkalieren.
Kathy Van Stone
@KathyVanStone Interessant, ich glaube, ich habe es nie versucht und nur angenommen, dass es analog funktioniert unwords.
Niklas B.
1
Es ist schön, dass die Standardbibliothek einige normale Funktionen zur Bearbeitung von Zeichenfolgen und Listen enthält, und es ist schön, dass Sie hier ein Beispiel veröffentlichen, da es in Haskell ziemlich schwierig ist, eine Dokumentation für diese Art der alltäglichen Programmierung zu finden.
Andrew Koster
4

Es ist nicht schwer, mit Foldr einen Einzeiler zu schreiben

join sep xs = foldr (\a b-> a ++ if b=="" then b else sep ++ b) "" xs
join " " ["is","there","such","a","function","?"]
Ilya Kharlamov
quelle
3
Es wäre vorteilhaft, eine Beschreibung hinzuzufügen; jemand hat es als minderwertig gekennzeichnet.
Arya McCarthy
3
joinBy sep cont = drop (length sep) $ concat $ map (\w -> sep ++ w) cont
Alaya
quelle
3

Einige andere Ideen für Implementierungen von intersperse und intercalate, wenn jemand interessiert ist:

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

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

xs >>= fist äquivalent zu concat (map f xs).

Alexis
quelle
2

Wenn Sie Ihre eigenen Versionen von intercalateund schreiben möchten 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
quelle
1
Warum beschränken Sie sich auf Saiten? Außerdem sind Ihre Parens rund um die Funktionsanwendung redundant.
Melpomene
Stimmt, interspersemuss nicht sein Strings, intercalatemüsste es aber zumindest sein Show, und wenn Sie es verwenden Showwürden, müssten Sie Stringtrotzdem mit s umgehen . Ich gewöhne mich immer noch daran, wie Haskell mit gemischten Infix- und Präfixfunktionen / -operatoren $
umgeht
intercalate :: [a] -> [[a]] -> [a]- warum Show? In Bezug auf die Syntax hat Haskell keine Präfixoperatoren (außer -, was ein Gräuel ist), und die Funktionsanwendung ist enger gebunden als jeder Infixoperator: x:s:intersperse s xsist in Ordnung (aber es liest sich viel besser, wenn Sie die Leerzeichen in x : s : intersperse s xsFolgendes einfügen : (Ich ziehe an) Ich verstehe nicht wirklich, warum die Leute die Räume gerne weglassen :)).
Melpomene
Richtig. Ich vergesse immer wieder, dass das Arbeiten mit Strings nur mit Listen funktioniert. ShowDas lag daran, dass ich davon ausgegangen bin, dass das Ergebnis a sein soll String. Mit "Infix- und Präfixfunktionen / Operatoren" meinte ich "Präfixfunktionen und Infixoperatoren", aber das war unklar. Unär -ist der Tod. Was die :s und andere Infix-Operatoren betrifft, hängt es stark vom Kontext ab, ob ich Leerzeichen verwende, aber ich bin immer lokal konsistent. zB (:)in einem Muster hat Match nie Leerzeichen, aber anderswo hängt es davon ab, ob es in Klammern steht und von meiner Stimmung.
Zoey Hewll