2010-01-24 38 views
5

Làm cách nào để viết một hàm trong Haskell, có chuỗi đầu vào theo định dạng a1a2a3 và mở rộng thành a1a2a2a3a3a3. Ví dụ: chuỗi đầu vào "mã" sẽ được mở rộng thành "coodddeeee"Học Haskell: Câu hỏi thao tác chuỗi

+0

Xin vui lòng gửi mã bạn đã viết để giải quyết việc này cho đến nay. Nếu không thì mọi người có thể nghi ngờ đây là bài tập về nhà. –

+0

Tôi đảm bảo với bạn, đây không phải là bài tập về nhà :) Tôi đã làm việc thông qua các excersises trong một cuốn sách Haskell và bộ não của tôi chỉ đóng băng lên trên này. Tất cả tôi biết tại thời điểm này là, tôi sẽ cần phải sử dụng nhà điều hành ++, một số loại thao tác mảng và có thể sử dụng chức năng chiều dài –

Trả lời

9

lẽ rất không hiệu quả :)

f :: Int -> [Char] -> [Char] 
f _ [] = [] 
f n (c:s) = (replicate n c) ++ (f (n+1) s) 

g :: [Char] -> [Char] 
g s = f 1 s 

.

*Main> g "code" 
"coodddeeee" 
+5

FYI: juxtaposition liên kết chặt chẽ hơn bất cứ điều gì nhưng @, vì vậy bạn có thể loại bỏ một vài dấu ngoặc đơn quá hoang tưởng. f n (c: s) = sao chép n C++ f (n + 1) s –

19

Vì vậy, bạn muốn nhân vật nth được lặp lại n lần.

f :: String -> String 
f x = concatMap g (zip x [1..]) 
    where 
     g (x,y) = replicate y x 

Tôi chắc chắn có cách dễ dàng hơn để thực hiện việc này.

Giải thích: Trước tiên, chúng tôi lấy chuỗi và ghép nối với vị trí của nó trong danh sách (bắt đầu từ 1). Đây là những gì zip hiện:

Prelude> zip "code" [1..] 
[('c',1),('o',2),('d',3),('e',4)] 

Sử dụng chức năng sao chép sao chép bất cứ điều gì bạn muốn y lần. Vì vậy, chúng tôi nhân rộng x, y lần.

Prelude> g ('z',4) 
"zzzz" 

Nếu chúng ta bản đồ chức năng này qua danh sách sản xuất bạn sẽ có được kết quả:

Prelude> map g $ zip "code" [1..] 
["c","oo","ddd","eeee"] 

Nếu bạn có một danh sách các chuỗi, bạn có thể nối chúng lại với nhau bằng concat. concatMap áp dụng hàm g cho mỗi cặp chữ cái và số và sau đó nối chuỗi vào kết quả cuối cùng.

Prelude> concat $ map g $ zip "code" [1..] 
"coodddeeee" 

Về cơ bản: concat $ map g ->concatMap g

EDIT: bây giờ nó hoạt động, nó cũng có thể được thực hiện trong một dòng thusly:

f x = concatMap (\(a,b)->replicate b a) $ zip x [1..] 

Output:

Prelude> f "lambda" 
"laammmbbbbdddddaaaaaa" 
+0

Jonno ... Bạn có thể giải thích câu trả lời đó, Như một người đang ở giai đoạn đầu học haskell, câu trả lời ở trên không có ý nghĩa với tôi. –

+0

Xem phần chỉnh sửa để giải thích –

+2

Tôi sẽ thay thế 'g' bằng' uncurry. flip replicate'. Điều tương tự, nhưng sử dụng các hàm thư viện Haskell chuẩn. –

15
import Control.Monad 
f = zip [1..] >=> uncurry replicate 

mang

Main> f "code" 
"coodddeeee" 
+1

Tốt! Đối với những người như tôi, người không biết loại người điều hành: "Thành phần Kleisli từ trái sang phải của các đơn vị:' (> =>) :: Monad m => (a -> mb) -> (b -> mc) -> (a -> mc) '" –

1
Prelude> let l = "code" in concat $ [take y $ repeat (last $ take y l) | y <- [1..length l]] 
"coodddeeee" 
4

Tại sao người ta ghét comprehensions danh sách?

Prelude> let f s = concat [ replicate x y | (x,y) <- zip [1..] s] 
Prelude> f "code" 
"coodddeeee" 

hoặc nếu bạn muốn phát điên với phần mở rộng

Prelude> :set -XParallelListComp 
Prelude> let f s = concat [ replicate x y | x <- [1..] | y <- s] 
Prelude> f "code" 
"coodddeeee"