在Haskell中创建指定长度的子字符串列表

时间:2014-12-17 10:27:09

标签: haskell

我编写了一个函数,该函数应该返回字符串的指定长度n的所有子字符串。它将从另一个函数调用,x将始终为0(我只用C语言编写,我只能想到一个计数器)。

allSubs :: Int -> Int -> String -> [String]
allSubs x n s
    |n>x = (take n (drop x (tail s))) ++ (allSubs (x+1) n s)
    |otherwise =

我希望上面的函数有意义,如果输入是

,在这个函数中
allSubs 0 2 "john"

它应该创建一个列表

["jo","oh","hn"]

但是我想用该列表调用另一个函数,但是我无法理解我是如何做到的?而且我不知道在其他情况下应该放什么?

1 个答案:

答案 0 :(得分:5)

根本不需要x。这个想法只是取字符串的初始n字符,然后递归调用allSubs作为字符串的尾部(除了第一个字符之外的所有字符),直到我们到达长度为字符串太短而无法取n个字符:

allSubs :: Int -> String -> [String]
allSubs n s
    | length s >= n = take n s : allSubs n (tail s)
    | otherwise = []

Live demo

一个直观的例子就是:

allSubs 3 "ABCDE"
"ABC" : allSubs 3 "BCDE"               -- take 3 "ABCDE" : allSubs 3 (tail "ABCDE")
"ABC" : "BCD" : allSubs 3 "CDE"        -- take 3 "BCDE" : allSubs 3 (tail "BCDE")
"ABC" : "BCD" : "CDE" : allSubs 3 "DE" -- "DE" is too short to go forward
"ABC" : "BCD" : "CDE" : []
["ABC", "BCD", "CDE"]

上述解决方案确实不是最佳的。优化的解决方案将遵循:

allSubs :: Int -> String -> [String]
allSubs n s = allSubs' (length s) n s
    where allSubs' :: Int -> Int -> String -> [String]
          allSubs' l n s
              | l >= n    = take n s : allSubs' (l - 1) n (tail s)
              | otherwise = []

Live demo

上述解决方案消除了在每次迭代时计算长度的O(n)成本。