Haskell 如何停止递归并在内存中生成列表
(1.)函数“sameString”返回一个布尔值,用于判断两个字符串是否相同,而不考虑大小写Haskell 如何停止递归并在内存中生成列表,haskell,recursion,Haskell,Recursion,(1.)函数“sameString”返回一个布尔值,用于判断两个字符串是否相同,而不考虑大小写 -- *Main> sameString "HeLLo" "HElLo" -- True -- *Main> sameString "Hello" "Hi there" -- False sameString :: String -> String -> Bool sameString str1 str2 | length str1 == length
-- *Main> sameString "HeLLo" "HElLo"
-- True
-- *Main> sameString "Hello" "Hi there"
-- False
sameString :: String -> String -> Bool
sameString str1 str2
| length str1 == length str2 = and [ a == b | (a,b) <- zip (capitalise str1) (capitalise str2) ]
| otherwise = False
-- *Main> prefix "bc" "abCDE"
-- False
-- *Main> prefix "Bc" "bCDE"
-- True
prefix :: String -> String -> Bool
prefix [] [] = True
prefix substr str
| sameString string' substr == True = True
| otherwise = False
where chop_str :: String -> String -> String
chop_str str substr = (take (length substr) str)
string' = chop_str str substr
(3.)函数“DropTill”返回第一个字符串首次出现后第二个字符串的内容。如果第二个字符串不包含作为子字符串的第一个字符串,则应返回空字符串
*Main> dropUntil "cd" "abcdef"
"ef"
dropUntil :: String -> String -> String
dropUntil substr [] = ""
dropUntil substr (s:tr)
| prefix substr (s:tr) == False = drop 1 s : dropUntil substr tr
| prefix substr (s:tr) == True =
现在问题来了。我在考虑用递归做dropUntil
我认为上述功能应该做的是:
1) 给定一个字符串和一个子字符串(子字符串不是该字符串的前缀)
它应该把绳子的头放下
并将空列表“”改为
。。。对剩余尾部和相同子字符串的递归调用
其背后的思想是不断删除列表的头,直到子字符串成为列表的前缀,然后函数将生成剩余的字符串作为结果
然而,我不知道该怎么做。我基本上想做的是
| prefix substr (s:tr) == True = "leftover_string"
其中,“leftover_string”是递归调用删除元素后剩下的内容,直到满足子字符串是余数前缀的条件
这可以按照我开始的方式进行吗?这就是你想要的吗
| prefix substr (s:tr) == True = drop (length substr) (s:tr)
一些注意事项:
此处存在类型错误:
| prefix substr (s:tr) == False = drop 1 s : dropUntil substr tr
^^^^^^^^
我想你只是想:
| prefix substr (s:tr) == False = dropUntil substr tr
在过去的几天里,我们遇到了很多问题,其中涉及到运行一个对等的
[x]
和一些其他的[x]
来查找isPrefixOf
。从那时起,在我的思维过程中出现的一个原始概念在这里非常有价值:
import Data.List
splitAtSublist :: ([x] -> Bool) -> [x] -> Maybe ([x], [x])
splitAtSublist pred list = find (pred . snd) $ zip (inits list) (tails list)
字符串“abcd”
的拆分zip(初始列表)(尾部列表)
看起来像[(“”,“abcd”),((“a”,“bcd”),(“ab”,“cd”),(“abc”,“d”),(“abcd”,“d”)]
。这将查找第一个元素,其中拆分的“尾端”满足谓词pred
要在此基础上获得Drop Until s,我们只需执行以下操作:
dropUntil p ls =
maybe "" (drop (length p) . snd) $
splitAtSublist (p `isPrefixOf`) ls
其中,isPrefixOf
来自数据。列表也是。替换为,我们发现根本不使用inits列表
,它只是变成:
dropUntil p = maybe "" (drop $ length p) . find (p `isPrefixOf`) . tails
这是我能得到的最简单的 (这个评论是离题的。)请记住,尤其是如果你是学生,“字母”,特别是Unicode,比你想象的要复杂得多。您的函数capitalize=map toUpper
,尤其是作为不区分大小写比较的代理,被认为是不好的做法。对于真实世界的使用,请考虑使用“谢谢”来指出可怕的类型错误。是的,这正是我的意思,而且很有道理!谢谢User5402提供了我想要的确切答案,但这也非常棒。我是Haskell的初学者,因此我必须查找一些函数,但我大致了解了它的要点。希望我能抽出时间仔细研究你的答案,我真的很感激,克里斯!
dropUntil p = maybe "" (drop $ length p) . find (p `isPrefixOf`) . tails