Czy istnieje funkcja haskell do łączenia listy z separatorem?


133

Czy istnieje funkcja konkatenacji elementów listy z separatorem? Na przykład:

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

Dzięki za każdą odpowiedź!


13
Wiem, że odpowiedzi lmgtfy są złe, ale warto zauważyć, że wyszukiwanie „String -> [String] -> String” w hoogle daje dokładnie to, czego chcesz. haskell.org/hoogle
sigfpe

3
do łączenia ze spacjami, które również maszunwords
epsilonhalbe

1
@sigfpe Komentarz boczny: Musiałbyś poszukać na [String] -> String -> Stringwypadek, gdyby w drugą stronę brakowało odpowiedzi, prawda?
Lay González

1
@ LayGonzález Wyszukiwanie zależy od permutacji. Na przykład wyszukiwanie [a] -> (a -> b) -> [b]zwrotów mapjako pierwszego wyniku.
gallais

Odpowiedzi:


232

Tak, jest :

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

intersperse jest nieco bardziej ogólny:

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

Ponadto w konkretnym przypadku, w którym chcesz połączyć znak spacji, jest unwords:

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

unlinesdziała podobnie, tylko że ciągi są implodowane przy użyciu znaku nowej linii i że znak nowej linii jest również dodawany na końcu. (To sprawia, że ​​jest to przydatne do serializacji plików tekstowych, które zgodnie ze standardem POSIX muszą kończyć się końcowym znakiem nowej linii)


Czy którykolwiek z nich może poradzić sobie z możliwymi pustymi ciągami?
CMCDragonkai

3
@CMCDragonkai Nie jestem pewien, do czego dokładnie się odnosisz, ale tak, wszystkie te funkcje pozwalają na użycie dowolnych ciągów znaków jako separatora i elementów. Na przykład intercalate "," ["some", "", "string"] = "some,,string"iintercalate "" ["foo", "bar"] = "foobar"
Niklas B.

3
unlinesdodaje nową linię do każdej linii, to znaczy unlines ["A", "B"] = "A\nB\n", że nie jest tym samym, co interkalacja.
Kathy Van Stone

@KathyVanStone Interesujące, chyba nigdy nie próbowałem i tylko założyłem, że działa to analogicznie do unwords.
Niklas B.

1
Fajnie, że w standardowej bibliotece są jakieś normalne funkcje do manipulacji na ciągach znaków i listach, i fajnie, że publikujesz tutaj przykład, ponieważ dość trudno jest znaleźć jakąkolwiek dokumentację do tego rodzaju codziennego programowania w Haskell.
Andrew Koster

4

Nie jest trudno napisać jedną linijkę za pomocą foldr

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

4
Dobrze byłoby dodać do tego opis; ktoś oznaczył go jako niskiej jakości.
Arya McCarthy

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

3

Kilka innych pomysłów na implementacje intersperse i interkalate, jeśli ktoś jest zainteresowany:

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

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

xs >>= fjest równoważne concat (map f xs).


2

Jeśli chcesz napisać własne wersje intercalatei 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
Po co ograniczać się do strun? Ponadto parens wokół aplikacji funkcji są zbędne.
melpomene

To prawda, że interspersenie musi tak być Strings, ale intercalatemusiałby być co najmniej Show, a jeśli tak używania Show, którą trzeba w jakiś sposób radzić sobie z nimi za pomocą Stringe tak. Nadal przyzwyczajam się do tego, jak Haskell radzi sobie z mieszanymi funkcjami / operatorami wrostków i prefiksów, i wolę $
nawiasy kwadratowe

intercalate :: [a] -> [[a]] -> [a]- dlaczego Show? Jeśli chodzi o składnię, Haskell nie ma żadnych operatorów prefiksów (poza tym -, co jest obrzydliwością), a aplikacja funkcji wiąże mocniej niż jakikolwiek operator wrostka: x:s:intersperse s xsjest w porządku (ale czyta znacznie lepiej, jeśli umieścisz spacje w: x : s : intersperse s xs(nie naprawdę nie rozumiem, dlaczego ludzie lubią pomijać przestrzenie wokół :)).
melpomene

Dobrze. Ciągle zapominam, że praca z napisami to tylko praca z listami. Showwynikało z tego, że zakładałem, że chcesz, aby wynik był String. Przez „funkcje / operatory przedrostków” miałem na myśli „funkcje przedrostkowe i operatory wrostkowe”, ale to było niejasne. Jednoargumentowe -to śmierć. Jeśli chodzi o :s i inne operatory infix, to, czy używam spacji, zależy w dużym stopniu od kontekstu, ale zawsze jestem lokalnie spójny. np. (:)w dopasowaniu wzorca nigdy nie ma spacji, ale gdzie indziej zależy to od tego, czy jest w nawiasach i od mojego nastroju.
Zoey Hewll
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.