我编写了一个函数,该函数应该返回字符串的指定长度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"]
但是我想用该列表调用另一个函数,但是我无法理解我是如何做到的?而且我不知道在其他情况下应该放什么?
答案 0 :(得分:5)
根本不需要x
。这个想法只是取字符串的初始n
字符,然后递归调用allSubs
作为字符串的尾部(除了第一个字符之外的所有字符),直到我们到达长度为字符串太短而无法取n
个字符:
allSubs :: Int -> String -> [String]
allSubs n s
| length s >= n = take n s : allSubs n (tail s)
| otherwise = []
一个直观的例子就是:
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 = []
上述解决方案消除了在每次迭代时计算长度的O(n)成本。