Чи є якась функція haskell для об'єднання списку з роздільником?


131

Чи є функція об'єднання елементів списку з роздільником? Наприклад:

> 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 Side коментар: Вам доведеться шукати на [String] -> String -> Stringвипадок, якщо інший спосіб не поверне відповіді, правда?
Закладіть Гонсалес

1
@ LayGonzález Пошук до перестановок. Наприклад, пошук [a] -> (a -> b) -> [b]повернень mapяк перший результат.
gallais

Відповіді:


228

Так, є :

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працює аналогічно, лише те, що рядки вбудовуються за допомогою символу newline та що символ newline також додається до кінця. (Це робить корисним для серіалізації текстових файлів, які повинні відповідати стандартному контуру 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

Деякі інші ідеї впровадження intersperse та intercalate, якщо хтось зацікавлений:

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).


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
Навіщо обмежувати себе рядками? Крім того, ваші паролі навколо програми функцій є зайвими.
мельпомена

Щоправда, intersperseцього не потрібно Strings, але intercalateпотрібно було б принаймні бути Show, і якщо ви все- таки користуєтесь Show, то вам знадобиться якийсь спосіб розібратися з ними за допомогою Strings. Я все ще звикаю до того, як Haskell має справу зі змішаними функціями / операторами приставки та префікса, і я віддаю перевагу дужці під час змішування, якщо я в кінцевому підсумку хочу скористатися$
Zoey Hewll

intercalate :: [a] -> [[a]] -> [a]- чому Show? Що стосується синтаксису, у Haskell немає жодних операторів префікса (за винятком випадків -, що це гидота), а додаток функції пов'язує жорсткіше, ніж будь-який оператор інфіксації: x:s:intersperse s xsдобре (але він читається набагато краще, якщо ви помістите пробіли у: x : s : intersperse s xs(Я не насправді не розумію, чому люди люблять залишати місця навколо :)).
мельпомена

Правильно. Я постійно забуваю, що робота з рядками - це просто робота зі списками. Showбуло тому, що я припускав, що ви хочете, щоб результат був таким String. Під «функціями / операторами інфіксації та префікса» я мав на увазі «функції префікса та оператори інфіксації», але це було незрозуміло. Унарний -- це смерть. Що стосується :s та інших операторів infix, то чи використовувати я пробіли, дуже залежить від контексту, але я завжди локально послідовний. наприклад, (:)у поєднанні з малюнком ніколи немає пробілів, але в інших місцях це залежить від того, чи це скорене, і від мого настрою.
Zoey Hewll
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.