Apakah ada fungsi haskell untuk menggabungkan daftar dengan pemisah?

131

Apakah ada fungsi untuk menggabungkan elemen daftar dengan pemisah? Sebagai contoh:

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

Terima kasih atas balasan!

Fopa Léon Constantin
sumber
13
Saya tahu jawaban lmgtfy itu buruk, tetapi perlu dicatat bahwa pencarian untuk "String -> [String] -> String" di hoogle mendapatkan apa yang Anda inginkan. haskell.org/hoogle
sigfpe
3
untuk bergabung dengan ruang yang Anda milikiunwords
epsilonhalbe
1
@sigfpe Komentar sisi: Anda harus mencari [String] -> String -> Stringseandainya cara lain tidak mengembalikan jawaban, kan?
Lay González
1
@ LayGonzález Pencarian terserah permutasi. Misalnya mencari [a] -> (a -> b) -> [b]pengembalian mapsebagai hasil pertama.
gallais

Jawaban:

228

Ya ada :

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

intersperse sedikit lebih umum:

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

Juga, untuk kasus khusus di mana Anda ingin bergabung dengan karakter spasi, ada unwords:

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

unlinesbekerja dengan cara yang sama, hanya bahwa string dilod menggunakan karakter baris baru dan bahwa karakter baris baru juga ditambahkan ke akhir. (Ini membuatnya berguna untuk membuat serialisasi file teks, yang harus per standar POSIX berakhir dengan baris tambahan)

Niklas B.
sumber
Adakah yang bisa mengatasi kemungkinan string kosong?
CMCDragonkai
3
@ CMCDragonkai Tidak yakin apa yang sebenarnya Anda maksud, tapi ya, semua fungsi ini memungkinkan string acak sebagai pemisah dan elemen. Misalnya, intercalate "," ["some", "", "string"] = "some,,string"danintercalate "" ["foo", "bar"] = "foobar"
Niklas B.
3
unlinesmenambahkan baris baru ke setiap baris unlines ["A", "B"] = "A\nB\n", jadi tidak sama dengan interkalasi.
Kathy Van Stone
@KathyVanStone Menarik, saya kira saya tidak pernah mencoba dan hanya menganggap itu bekerja secara analog unwords.
Niklas B.
1
Sangat menyenangkan bahwa ada beberapa fungsi manipulasi string dan daftar normal di pustaka standar, dan senang Anda memposting contoh di sini, karena cukup sulit untuk menemukan dokumentasi apa pun untuk pemrograman sehari-hari semacam ini di Haskell.
Andrew Koster
4

Tidak sulit menulis one-liner menggunakan foldr

join sep xs = foldr (\a b-> a ++ if b=="" then b else sep ++ b) "" xs
join " " ["is","there","such","a","function","?"]
Ilya Kharlamov
sumber
3
Akan bermanfaat untuk menambahkan deskripsi pada ini; seseorang menandainya sebagai kualitas rendah.
Arya McCarthy
3
joinBy sep cont = drop (length sep) $ concat $ map (\w -> sep ++ w) cont
Alaya
sumber
3

Beberapa ide lain implementasi intersperse dan intercalate, jika seseorang tertarik:

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

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

xs >>= fsetara dengan concat (map f xs).

Alexis
sumber
2

Jika Anda ingin menulis versi intercalatedan 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)
Zoey Hewll
sumber
1
Mengapa membatasi diri Anda pada string? Selain itu, orangtua Anda di sekitar aplikasi fungsi berlebihan.
melpomene
Benar, interspersetidak perlu menjadi Strings, tetapi intercalateperlu setidaknya Show, dan jika Anda melakukan penggunaan Show, Anda akan perlu beberapa cara untuk berurusan dengan mereka menggunakan Strings pula. Saya masih membiasakan diri dengan bagaimana Haskell berurusan dengan fungsi / operator infiks dan awalan campuran, dan saya lebih suka memberi tanda kurung saat pencampuran jika saya akhirnya ingin menggunakan$
Zoey Hewll
intercalate :: [a] -> [[a]] -> [a]- mengapa Show? Sedangkan untuk sintaks, Haskell tidak memiliki operator awalan (kecuali untuk -, yang merupakan kekejian), dan aplikasi fungsi mengikat lebih ketat daripada operator infiks lainnya: x:s:intersperse s xsbaik-baik saja (tetapi bunyinya jauh lebih baik jika Anda menempatkan spasi di: x : s : intersperse s xs(saya tidak benar-benar mengerti mengapa orang suka meninggalkan ruang di sekitar :)).
melpomene
Baik. Saya selalu lupa bahwa bekerja dengan string hanya bekerja dengan daftar. Showkarena saya berasumsi Anda ingin hasilnya menjadi String. Dengan "infix dan fungsi awalan / operator" Maksud saya "fungsi awalan dan operator infiks", tapi itu tidak jelas. Unary -adalah kematian. Sedangkan untuk :s dan operator infiks lainnya, apakah saya menggunakan spasi sangat tergantung pada konteks, tapi saya selalu konsisten secara lokal. misalnya, (:)dalam pertandingan pola tidak pernah ada spasi, tetapi di tempat lain itu tergantung pada apakah itu tanda kurung dan pada suasana hati saya.
Zoey Hewll