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ź!
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ź!
unwords
[String] -> String -> String
wypadek, gdyby w drugą stronę brakowało odpowiedzi, prawda?
[a] -> (a -> b) -> [b]
zwrotów map
jako pierwszego wyniku.
Odpowiedzi:
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 ?"
unlines
dział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)
intercalate "," ["some", "", "string"] = "some,,string"
iintercalate "" ["foo", "bar"] = "foobar"
unlines
dodaje nową linię do każdej linii, to znaczy unlines ["A", "B"] = "A\nB\n"
, że nie jest tym samym, co interkalacja.
unwords
.
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","?"]
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 >>= f
jest równoważne concat (map f xs)
.
Jeśli chcesz napisać własne wersje intercalate
i 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)
intersperse
nie musi tak być Strings
, ale intercalate
musiał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ą String
e tak. Nadal przyzwyczajam się do tego, jak Haskell radzi sobie z mieszanymi funkcjami / operatorami wrostków i prefiksów, i wolę $
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 xs
jest 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ół :
)).
Show
wynikał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.