简体   繁体   English

在haskell中制作takeUntil函数

[英]making a takeUntil function in haskell

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" 我想要一个函数,当给定一个字符串,例如“ ab”和“ cdabd”时,将在这两个字符串上使用时,它将输出“ 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)

There is a lot of ways to do this, but continuing with your path, try the following: 有很多方法可以做到这一点,但是继续您的尝试,请尝试以下操作:

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

Some outputs: 一些输出:

takeUntil "ab" "cdabd"
"cd"

takeUntil "b" "cdabd"
"cda"

takeUntil "d" "cdabd"
"c"

takeUntil "c" "cdabd"
""

takeUntil "xxx" "cdabd"
"cdabd"

EDIT: 编辑:

The OP wants the function to be case-insensitive. OP希望该功能不区分大小写。

Well, again you can do that in lot of ways. 好了,您可以通过很多方式来做到这一点。 For example you can write a lowerCase function like (i think you already have it in Data.Text ): 例如,您可以编写一个lowerCase函数,例如(我认为您已经在Data.Text拥有它):

import qualified Data.Char as Char

lowerCase :: String -> String
lowerCase [] = []
lowerCase (x:xs) = (Char.toLower x):(lowerCase xs)

And then use it like (maybe ugly and not very practical): 然后像这样使用它(可能很难看,但不太实用):

takeUntil (lowerCase "cd") (lowerCase "abcDe")
"ab"

That is the result you expect. 那是您期望的结果。

Also, you can use that lowerCase function inside takeUntil : 另外,您可以在takeUntil使用lowerCase函数:

-- ...
takeUntil xs (y:ys) = if  isPrefixOf (lowerCase xs) (lowerCase (y:ys))
-- ...

So, you can just do: 因此,您可以执行以下操作:

takeUntil "cd" "abcDe"
"ab"

Anyway, i think the best option is that one @bheklilr suggested. 无论如何,我认为最好的选择是建议一个@bheklilr。 Make your own isPrefixOfCaseless function. 制作自己的isPrefixOfCaseless函数。

I hope this helps. 我希望这有帮助。

Within the numerous approaches to define takeUntil , consider using Data.Text functions as follows, 在定义takeUntil的众多方法中,请考虑使用Data.Text函数,如下所示,

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

Note that pack converts a String to a Text , whereas uncpak does the inverse; 请注意, packString转换为Text ,而uncpak则相反。 toCaseFold for case insensitive operations; toCaseFold用于不区分大小写的操作; breakOn delivers a pair where the first element includes text until the first (possible) match. breakOn提供一对,其中第一个元素包括文本,直到第一个(可能)匹配为止。

Update 更新

This approach covers tests already suggested, yet it does not preseve original String for instance here, 这种方法涵盖了已经建议的测试,但是在这里并没有假装原始String

takeUntil "e" "abcDe"
"abcd"

A work around this involves for instance the splitting by index at the break point. 解决此问题的方法包括,例如在断点处按索引拆分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM