String 带字符串的复杂模式匹配
我有一个字符串列表,如下所示:String 带字符串的复杂模式匹配,string,haskell,String,Haskell,我有一个字符串列表,如下所示: xs = ["xabbaua", "bbbaacv", "ggfeehhaa", "uyyttaccaa", "ibbatb"] 我只想在列表中找到包含和vocel,后跟两个b,后跟任何字符和元音的字符串。在Haskell中,这样的简单匹配是如何完成的。有没有比正则表达式更好的解决方案?谁能帮我举个例子吗?谢谢。您可以尝试此功能,尽管这可能不是最好的方法: elem' :: String -> String -> Bool elem' p xs =
xs = ["xabbaua", "bbbaacv", "ggfeehhaa", "uyyttaccaa", "ibbatb"]
我只想在列表中找到包含和vocel,后跟两个b,后跟任何字符和元音的字符串。在Haskell中,这样的简单匹配是如何完成的。有没有比正则表达式更好的解决方案?谁能帮我举个例子吗?谢谢。您可以尝试此功能,尽管这可能不是最好的方法:
elem' :: String -> String -> Bool
elem' p xs = any (p==) $ map (take $ length p) $ tails xs
用法:
filter (elem' "bb") ["xxbbaua", "bbbaacv", "ggfeehhaa", "uyyttaccaa", "bbbaab"]
或
如果你绝对反对使用正则表达式,你可以只使用模式匹配和递归,尽管这很难看
xs = ["xabbaua", "bbbaacv", "ggfeehhaa", "uyyttaccaa", "ibbatb"]
vowel = "aeiou"
filter' strs = filter matches strs
matches [] = False
matches str@(x:'b':'b':_:y:xs)
| x `elem` vowel && y `elem` vowel = True
| otherwise = matches $ tail str
matches (x:xs) = matches xs
调用
filter'xs
将返回[“xabbaua”]
,我认为这是必需的结果。一种方法是构建一种小型模式匹配语言并将其嵌入Haskell
在您的示例中,模式基本上是字符规范的列表。让我们定义一种类型的抽象字符,其值将用作此类规范
data AbsChar = Exactly Char | Vowel | Any
还有一个“解释器”,告诉我们字符是否符合规范:
(=?) :: AbsChar -> Char -> Bool
Exactly c' =? c = c == c'
Vowel =? c = c `elem` "aeiou"
Any =? c = True
例如,元音=?'x'
将产生False
,而元音=?'“
将产生True
事实上,模式只是一系列抽象字符:
type Pattern = [AbsChar]
接下来,我们编写一个函数,测试字符串的前缀是否与给定模式匹配:
matchesPrefix :: Pattern -> String -> Bool
matchesPrefix [] _ = True
matchesPrefix (a : as) (c : cs) = a =? c && matchesPrefix as cs
matchesPrefix _ _ = False
例如:
> matchesPrefix [Vowel, Exactly 'v'] "eva"
True
> matchesPrefix [Vowel, Exactly 'v'] "era"
False
> tails "xabbaua"
["xabbaua","abbaua","bbaua","baua","aua","ua","a",""]
> let pat = [Vowel, Exactly 'b', Exactly 'b', Any, Vowel]
> select pat ["xabbaua", "bbbaacv", "ggfeehhaa", "uyyttaccaa", "ibbatb"]
["xabbaua"]
由于我们不希望限制自己匹配前缀,而是匹配单词中的任何位置,因此我们的下一个函数将匹配字符串的每个结束段的前缀:
containsMatch :: Pattern -> String -> Bool
containsMatch pat = any (matchesPrefix pat) . tails
它使用了函数tails
,可以在模块Data.List
中找到,但为了使此解释更加完整,我们也可以轻松定义自己:
tails :: [a] -> [[a]]
tails [] = [[]]
tails l@(_ : xs) = l : tails xs
例如:
> matchesPrefix [Vowel, Exactly 'v'] "eva"
True
> matchesPrefix [Vowel, Exactly 'v'] "era"
False
> tails "xabbaua"
["xabbaua","abbaua","bbaua","baua","aua","ua","a",""]
> let pat = [Vowel, Exactly 'b', Exactly 'b', Any, Vowel]
> select pat ["xabbaua", "bbbaacv", "ggfeehhaa", "uyyttaccaa", "ibbatb"]
["xabbaua"]
最后,您要查找的从包含匹配段的列表中选择所有字符串的函数简单地写为:
select :: Pattern -> [String] -> [String]
select = filter . containsMatch
让我们在您的示例中进行测试:
> matchesPrefix [Vowel, Exactly 'v'] "eva"
True
> matchesPrefix [Vowel, Exactly 'v'] "era"
False
> tails "xabbaua"
["xabbaua","abbaua","bbaua","baua","aua","ua","a",""]
> let pat = [Vowel, Exactly 'b', Exactly 'b', Any, Vowel]
> select pat ["xabbaua", "bbbaacv", "ggfeehhaa", "uyyttaccaa", "ibbatb"]
["xabbaua"]
您可以将经典过滤器函数与任何regexp库结合使用。您的模式非常简单,可用于任何regexp库:
filter (=~ "bb.[aeiuy]") xs
Haskell中regexps令人困惑的部分是,有一个非常强大的通用API(在regex base中)以同样的方式将它们用于所有特定的库和您希望的多结果类型(Bool、String、Int…)。对于基本用途,它应该主要按照您的意思工作(tm)。对于您的特定需求,regex-posix应该足够了(并且附带haskell平台,所以不需要正常安装)。所以别忘了导入它:
import Text.Regex.Posix
这应该向您展示regex API的基础知识。如果您有其他需要,它现在有点过时了,但基础知识保持不变,只是regex base的细节有所改变。这是regex的理想场所。你为什么不想使用它呢?我看了各种Regex模块,但是文档非常稀疏,很难理解。如何获得只包含匹配单词的筛选列表?这不起作用。例如,我需要匹配bbau而不是bbat。参数
p
用于模式。如果你给“bbau”,它会过滤有“bbau”的字符串。好的,谢谢,我明白你的意思。我试图为我的问题提供一个简单的例子,但太简单了。我需要在几个位置匹配几个可能的字符。很抱歉给你带来了困惑。