问题
I have written a function which should return all substrings of a specified length, n, of a string. It will be called from another function and x will always be initially 0 ( I have only written in C and a counter is all I could think of).
allSubs :: Int -> Int -> String -> [String]
allSubs x n s
|n>x = (take n (drop x (tail s))) ++ (allSubs (x+1) n s)
|otherwise =
I hope the above function makes sense, in this function if the input was
allSubs 0 2 "john"
It should create a list
["jo","oh","hn"]
But I'd like to call another function with that list, but I can't get my head around how I could do that? And I don't know what to put in the otherwise case?
回答1:
You don't need x
at all. The idea is simply to take the initial n
characters of the string, then call recursively allSubs
for the tail (everything except the first character) of the string, until we reach the point where the length of the string is too short to take n
characters:
allSubs :: Int -> String -> [String]
allSubs n s
| length s >= n = take n s : allSubs n (tail s)
| otherwise = []
Live demo
A visual example is this:
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"]
The above solution is indeed not optimal. And optimized solution would be along the lines of:
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
The above solution removes the O(n) cost of computing the length at every iteration.
来源:https://stackoverflow.com/questions/27523398/creating-a-list-of-substrings-of-a-specified-length-in-haskell