在haskell中生成takeUntil函数
我想做一个函数,当给定一个字符串如“ab”和“cdabd”时,它将在这两个字符串上使用,它将输出“cd” 到目前为止我还有这个在haskell中生成takeUntil函数,haskell,take,Haskell,Take,我想做一个函数,当给定一个字符串如“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
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)
有很多方法可以做到这一点,但继续您的路径,请尝试以下方法:
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希望函数不区分大小写
好吧,同样,你可以通过很多方式做到这一点。例如,您可以编写一个小写
函数,如(我想您在Data.Text
中已经有了它):
然后像这样使用它(可能很丑而且不太实用):
这就是你所期望的结果
此外,您还可以使用takeUntil
中的小写
函数:
-- ...
takeUntil xs (y:ys) = if isPrefixOf (lowerCase xs) (lowerCase (y:ys))
-- ...
所以,你可以这样做:
takeUntil "cd" "abcDe"
"ab"
无论如何,我认为最好的选择是@bheklillr建议的。让您自己的isPrefixOfCaseless
功能
我希望这有帮助。 < P>在定义<代码>直到的多种方法中,考虑使用以下函数,
takeUntil :: String -> String -> String
takeUntil sep txt = unpack $ fst $ breakOn (pack sep) (toCaseFold $ pack txt)
请注意,pack
将字符串
转换为文本
,而unpak
则相反toCaseFold
用于不区分大小写的操作breakn
提供一对,其中第一个元素包含文本,直到第一个(可能)匹配为止
更新
这种方法涵盖了已经建议的测试,但它没有保存原始的字符串
,例如
takeUntil "e" "abcDe"
"abcd"
解决这一问题的方法包括,例如,在断点处按索引进行拆分。您的定义有点错误,您的意思是最后4行的
takeUntil
?是的。如果你能发布包含的代码,或者至少是类型签名和它的功能的更具体的描述,那将非常有帮助。我猜我可能需要一个帮助函数来定义如果xs在ys中会发生什么。helper函数应该在匹配两个字符串之前切断所有内容,即“ab”“cdab”=“cd”解决此问题的方法很多,但我认为使用contains
会让事情变得困难。首先,如果我传入takeUntil“ab”“abcdab”
,该怎么办?使用contains
,将返回”
,而不是“cdab”
。直接使用isPrefixOf
将是一个更好的选择,就像@JosEdu所做的那样。谢谢,但问题是我需要使它不区分大小写,这样如果“cd”“abcDe”,它仍然会给我“ab”尝试在xs
和y
上使用toLower
fromData.Char
,take的第一个案例被第二个案例包含,因此可以删除它。另外,tail(y:ys)
可以简化为ys
@Nicholas如果您想执行此检查而不区分大小写,我建议创建一个isPrefixOfCaseless
(比isPrefixOfCaseInsensitive
短的名称)函数,在其参数上本地映射到lower
。您最终会复制一些操作,但在这种情况下,最好让它工作,而不是让它尽快运行。对,caselessPrefixOf pre-list=isPrefixOf(map-toLower-pre)(map-toLower-list)
很有价值。您也可以使用数据列表中的其他函数takeUntil xs ys=maybe ys fst$find(isPrefixOf xs.snd)$zip(inits ys)(tails ys)
将其简化为一个具有复杂逻辑的单行程序,您可以在caselessPrefixOf
中进行交换。
takeUntil :: String -> String -> String
takeUntil sep txt = unpack $ fst $ breakOn (pack sep) (toCaseFold $ pack txt)
takeUntil "e" "abcDe"
"abcd"