[英]making a takeUntil function in haskell
我想要一個函數,當給定一個字符串,例如“ 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 :: 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希望該功能不區分大小寫。
好了,您可以通過很多方式來做到這一點。 例如,您可以編寫一個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"
那是您期望的結果。
另外,您可以在takeUntil
使用lowerCase
函數:
-- ...
takeUntil xs (y:ys) = if isPrefixOf (lowerCase xs) (lowerCase (y:ys))
-- ...
因此,您可以執行以下操作:
takeUntil "cd" "abcDe"
"ab"
無論如何,我認為最好的選擇是建議一個@bheklilr。 制作自己的isPrefixOfCaseless
函數。
我希望這有幫助。
在定義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"
解決此問題的方法包括,例如在斷點處按索引拆分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.