Есть ли какая-нибудь функция haskell для объединения списка с разделителем?

133

Есть ли функция для объединения элементов списка с разделителем? Например:

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

Спасибо за любой ответ!

Фопа Леон Константин
источник
13
Я знаю, что lmgtfy плохие ответы, но стоит отметить, что поиск «String -> [String] -> String» на hoogle дает именно то, что вы хотите. haskell.org/hoogle
sigfpe
3
для объединения с пробелами, которые у вас тоже естьunwords
epsilonhalbe
1
@sigfpe Боковой комментарий: вам придется искать, [String] -> String -> Stringесли другой способ не вернет ответа, верно?
Lay González
1
@ LayGonzález Возможен поиск до перестановок. Например, поиск [a] -> (a -> b) -> [b]возвращается mapкак первый результат.
gallais

Ответы:

229

Да, есть :

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

intersperse немного более общий:

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

Кроме того, для конкретного случая, когда вы хотите присоединиться с пробелом, есть unwords:

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

unlinesработает аналогично, только строки разворачиваются с использованием символа новой строки и что символ новой строки также добавляется в конец. (Это делает его полезным для сериализации текстовых файлов, которые в соответствии со стандартом POSIX должны заканчиваться новой строкой в ​​конце)

Никлас Б.
источник
Может ли что-нибудь из этого иметь дело с возможными пустыми строками?
CMCDragonkai
3
@CMCDragonkai Не уверен, что именно вы имеете в виду, но да, все эти функции позволяют использовать произвольные строки как в качестве разделителя, так и в качестве элементов. Например, intercalate "," ["some", "", "string"] = "some,,string"иintercalate "" ["foo", "bar"] = "foobar"
Никлас Б.
3
unlinesдобавляет новую строку к каждой строке, то есть unlines ["A", "B"] = "A\nB\n", это не то же самое, что и вставка.
Кэти Ван Стоун
@KathyVanStone Интересно, думаю, я никогда не пробовал и только предполагал, что он работает аналогично unwords.
Никлас Б.
1
Приятно, что в стандартной библиотеке есть некоторые обычные функции управления строками и списками, и приятно, что вы публикуете здесь пример, потому что довольно сложно найти какую-либо документацию для такого рода повседневного программирования в Haskell.
Эндрю Костер
4

Нетрудно написать однострочник с помощью foldr

join sep xs = foldr (\a b-> a ++ if b=="" then b else sep ++ b) "" xs
join " " ["is","there","such","a","function","?"]
Илья Харламов
источник
3
Было бы полезно добавить к этому описание; кто-то отметил его как низкое качество.
Арья Маккарти
3
joinBy sep cont = drop (length sep) $ concat $ map (\w -> sep ++ w) cont
Alaya
источник
3

Еще несколько идей реализации вкраплений и вставок, если кому-то интересно:

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

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

xs >>= fэквивалентно concat (map f xs).

Alexis
источник
2

Если вы хотите написать свои собственные версии intercalateи 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
Зачем ограничиваться струнами? Кроме того, ваши пары вокруг приложения функции избыточны.
Melpomene
Правда, intersperseне нужно быть Strings, но intercalateдолжны были бы быть по крайней мере Show, и если вы действительно использовать Show, вам нужен способ , чтобы справиться с ними , используя Strings в любом случае. Я все еще привыкаю к ​​тому, как Haskell имеет дело со смешанными инфиксными и префиксными функциями / операторами, и я предпочитаю использовать скобки при микшировании на случай, если я в конечном итоге $
захочу
intercalate :: [a] -> [[a]] -> [a]- почему Show? Что касается синтаксиса, то в Haskell нет никаких префиксных операторов (за исключением -, который является мерзостью), а приложение-функция связывает более жестко, чем любой инфиксный оператор: x:s:intersperse s xsэто нормально (но он читается намного лучше, если вы вставляете пробелы в: x : s : intersperse s xs(Я не Не совсем понимаю, почему люди любят оставлять пустые места вокруг :)).
melpomene
Правильно. Я все время забываю, что работа со строками - это просто работа со списками. Showбыло потому, что я предполагал, что вы хотите, чтобы результат был String. Под «инфиксными и префиксными функциями / операторами» я имел в виду «префиксные функции и инфиксные операторы», но это было неясно. Унарный -- это смерть. Что касается :s и других инфиксных операторов, то использование пробелов сильно зависит от контекста, но я всегда локально согласован. например, (:)в сопоставлении с шаблоном никогда не бывает пробелов, но в другом месте это зависит от того, заключено ли оно в квадратные скобки, и от моего настроения.
Zoey Hewll