我想创建一个函数,当给出一个字符串,例如“ab”和“cdabd”时,它将用于这两个字符串,它将输出“cd”
到目前为止我还有这个
takeUntil :: String -> String -> String
takeUntil [] [] = []
takeUntil xs [] = []
takeUntil [] ys = []
takeUntil xs ys = if contains xs ys then -- ???? I get stuck here.
contains函数是我之前定义的函数(整个函数应该不区分大小写) 包含功能:
contains :: String -> String -> Bool
contains _ [] = True
contains [] _ = False
contains xs ys = isPrefixOf (map toLower ys) (map toLower xs) || contains (tail(map toLower xs) (map toLower ys)
答案 0 :(得分:3)
有很多方法可以做到这一点,但继续你的路径,尝试以下方法:
import Data.List
takeUntil :: String -> String -> String
takeUntil [] [] = [] --don't need this
takeUntil xs [] = []
takeUntil [] ys = []
takeUntil xs (y:ys) = if isPrefixOf xs (y:ys)
then []
else y:(takeUntil xs (tail (y:ys)))
一些输出:
takeUntil "ab" "cdabd"
"cd"
takeUntil "b" "cdabd"
"cda"
takeUntil "d" "cdabd"
"c"
takeUntil "c" "cdabd"
""
takeUntil "xxx" "cdabd"
"cdabd"
修改强>
OP希望函数不区分大小写。
那么,你可以在很多方面做到这一点。例如,您可以编写一个lowerCase
函数(我认为您已经在Data.Text
中拥有它):
import qualified Data.Char as Char
lowerCase :: String -> String
lowerCase [] = []
lowerCase (x:xs) = (Char.toLower x):(lowerCase xs)
然后使用它(可能是丑陋而不是很实用):
takeUntil (lowerCase "cd") (lowerCase "abcDe")
"ab"
这是你期望的结果。
此外,您可以在lowerCase
内使用takeUntil
函数:
-- ...
takeUntil xs (y:ys) = if isPrefixOf (lowerCase xs) (lowerCase (y:ys))
-- ...
所以,你可以这样做:
takeUntil "cd" "abcDe"
"ab"
无论如何,我认为最好的选择是@bheklilr建议。制作自己的isPrefixOfCaseless
功能。
我希望这会有所帮助。
答案 1 :(得分:0)
在众多定义takeUntil
的方法中,请考虑使用Data.Text函数,如下所示,
takeUntil :: String -> String -> String
takeUntil sep txt = unpack $ fst $ breakOn (pack sep) (toCaseFold $ pack txt)
请注意,pack
会将String
转换为Text
,而uncpak
会反转toCaseFold
。 breakOn
用于不区分大小写的操作; String
提供了一对,其中第一个元素包含文本,直到第一个(可能的)匹配。
<强>更新强>
此方法涵盖了已建议的测试,但此处并未预先设置原始takeUntil "e" "abcDe"
"abcd"
,
{{1}}
解决这个问题涉及到例如在断点处通过索引进行拆分。