2012-02-10 17 views
86

Czy istnieje funkcja łączenia elementów listy za pomocą separatora? Na przykład:Czy istnieje jakaś funkcja haskell do łączenia listy z separatorem?

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

Dzięki za odpowiedź!

+11

wiem lmgtfy odpowiedzi są złe, ale warto zauważyć, że poszukiwanie „String -> [String] -> String” na hoogle robi tylko to, co chcesz. http://www.haskell.org/hoogle/ – sigfpe

+2

do łączenia ze spacjami również masz 'unwords' – epsilonhalbe

+1

@sigfpe Komentarz boczny: Musisz szukać' [String] -> String -> String' w przypadku, gdy inny sposób nie zwraca odpowiedzi, prawda? –

Odpowiedz

160

Tak, there is:

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

intersperse jest nieco bardziej ogólnie:

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 dołączyć z charakterem miejsca, nie ma unwords:

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

unlines działa podobnie tylko, że łańcuchy są implodowane za pomocą znaku nowego wiersza, a znak końca linii jest również dodawany do końca. (To czyni go użytecznym dla szeregowania pliki tekstowe, które muszą za POSIX standardowej końca z nową linią krocząca)

+0

Czy któryś z nich może dotyczyć możliwych pustych łańcuchów? – CMCDragonkai

+3

@CMCDragonkai Nie masz pewności, do czego dokładnie się odwołujesz, ale tak, wszystkie te funkcje umożliwiają dowolne ciągi jako separator i elementy. Na przykład "interkalacja", "[" niektóre "," "," ciąg "] =" niektóre, ciąg "' i "interkalacja" "[" foo "," bar "] =" foobar "' –

+0

'unlines 'dodaje znak nowej linii do każdej linii, czyli' unlines ["A", "B"] = "A \ nB \ n" ", więc nie jest to to samo, co interkalacja. –

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

Jeśli chciałeś napisać swoje 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) 
+1

Dlaczego ograniczasz się do ciągów? Również twoje parens wokół aplikacji funkcji są zbędne. – melpomene

+0

Prawda, 'intersperse' nie musi być' Strings', ale 'intercalate' musi przynajmniej być' Show', a jeśli użyjesz 'Show', będziesz potrzebował jakiegoś sposobu radzenia sobie z nimi za pomocą' Stringa ' w każdym razie. Wciąż się przyzwyczaiłem do tego, jak Haskell radzi sobie z mieszanymi infiksami i prefiksami/operatorami, a ja preferuję bracketing podczas miksowania, w przypadku gdy w końcu chcę użyć '$' –

+0

'intercalate :: [a] -> [[a ]] -> [a] '- dlaczego' Show'? Co do składni, Haskell nie ma żadnych operatorów prefiksów (z wyjątkiem '-', który jest obrzydliwością), a aplikacja funkcji wiąże się ciaśniej niż jakikolwiek operator infiksowania:' x: s: intersperse s xs' jest w porządku (ale czyta o wiele lepiej, jeśli wstawisz spacje: 'x: s: intersperse s xs' (naprawdę nie rozumiem, dlaczego ludzie lubią pomijać spacje wokół': ')). – melpomene

1

to nie jest trudno napisać jedno-liner korzystając foldr

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

Byłoby korzystne, aby dodać opis do tego; ktoś oznaczył go jako niskiej jakości. –

Powiązane problemy