2

I want make a function which when given a string eg "ab" and "cdabd" when it will be used on these two strings it will output "cd"

I have this up to now

takeUntil :: String -> String -> String
takeUntil [] [] = []
takeUntil xs [] = []
takeUntil [] ys = []
takeUntil xs ys = if contains xs ys then -- ???? I get stuck here. 

the contains function is one in which I had defined previously(this whole function should be case insensitive) contains function:

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)
4

2 回答 2

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功能。

我希望这有帮助。

于 2014-10-23T14:16:01.760 回答
0

在定义的众多方法中takeUntil,考虑使用Data.Text函数,如下所示,

takeUntil :: String -> String -> String
takeUntil sep txt =  unpack $ fst $ breakOn (pack sep) (toCaseFold $ pack txt)

请注意,pack将 a 转换String为 a Text,而反之uncpaktoCaseFold对于不区分大小写的操作;breakOn提供一对,其中第一个元素包含文本,直到第一个(可能的)匹配。

更新

这种方法涵盖了已经建议的测试,但它并不保留原始String例如这里,

takeUntil "e" "abcDe"
"abcd"

解决此问题的方法涉及例如在断点处按索引拆分。

于 2014-10-24T06:55:46.717 回答