2

次のような文字列のリストがあります。

xs = ["xabbaua", "bbbaacv", "ggfeehhaa", "uyyttaccaa", "ibbatb"]

リスト内で、 と vocel の後に 2 つの b が続き、その後に任意の文字と母音が続く文字列のみを検索したいと考えています。このような単純な一致は Haskell でどのように行われますか。正規表現よりも良い解決策はありますか? 誰かが例を手伝ってくれますか? ありがとう。

4

4 に答える 4

3

従来のフィルター関数を任意の正規表現ライブラリと組み合わせて使用​​できます。あなたのパターンは十分に単純なので、これはどの正規表現ライブラリでも機能します:

filter (=~ "bb.[aeiuy]") xs

Haskell の正規表現の紛らわしい部分は、すべての特定のライブラリと希望する複数の結果の型 (Bool、String、Int. ..)。基本的な使用法では、ほとんどの場合、意図したとおりに機能するはずです(tm)。特定のニーズに対しては、regex-posix で十分です (また、haskell プラットフォームに付属しているため、通常はインストールする必要はありません)。したがって、インポートすることを忘れないでください:

import Text.Regex.Posix

このチュートリアルでは、他のニーズがある場合に正規表現 API の基本を説明する必要があります。現在は少し古くなっていますが、基本は同じままで、正規表現ベースの詳細のみが変更されています。

于 2012-07-12T12:47:49.083 に答える
3

1 つのアプローチは、小さなパターン マッチング言語を構築し、それを Haskell に埋め込むことです。

あなたの例では、パターンは基本的に文字仕様のリストです。値がそのような仕様として機能する抽象文字のタイプを定義しましょう。

data AbsChar  =  Exactly Char | Vowel | Any

文字が仕様​​に一致するかどうかを伝える「インタープリター」と一緒に:

(=?)  ::  AbsChar -> Char -> Bool
Exactly c' =? c  =  c == c'
Vowel      =? c  =  c `elem` "aeiou"
Any        =? c  =  True

たとえば、Vowel =? 'x'は を生成Falseしますが、Vowel =? 'a'は を生成し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

一致するプレフィックスに制限するのではなく、単語内の任意の場所に一致させたいため、次の関数は文字列のすべての末尾セグメントのプレフィックスに一致します。

containsMatch  ::  Pattern -> String -> Bool
containsMatch pat  =  any (matchesPrefix pat) . tails

tailsモジュールにある関数を使用しますData.Listが、この説明を自己完結型にするために、自分自身も簡単に定義できます。

tails  ::  [a] -> [[a]]
tails []          =  [[]]
tails l@(_ : xs)  =  l : tails xs

例えば:

> tails "xabbaua"
["xabbaua","abbaua","bbaua","baua","aua","ua","a",""]

さて、最後に、一致するセグメントを含むリストからすべての文字列を選択する、探していた関数は次のように簡単に記述されます。

select  ::  Pattern -> [String] -> [String]
select  =  filter . containsMatch

あなたの例でそれをテストしましょう:

> let pat = [Vowel, Exactly 'b', Exactly 'b', Any, Vowel]
> select pat ["xabbaua", "bbbaacv", "ggfeehhaa", "uyyttaccaa", "ibbatb"]
["xabbaua"]
于 2012-07-12T10:01:05.903 に答える
1

まあ、これは最良の方法ではないかもしれませんが、あなたはこの関数を試すことができます:

elem' :: String -> String -> Bool
elem' p xs = any (p==) $ map (take $ length p) $ tails xs

使用法:

filter (elem' "bb") ["xxbbaua", "bbbaacv", "ggfeehhaa", "uyyttaccaa", "bbbaab"]

また

bbFilter = filter (elem' "bb")
于 2012-07-12T01:16:07.870 に答える
1

Regex を使用することに絶対に反対する場合は、パターン マッチングと再帰だけで行うことができますが、見栄えは悪くなります。

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"]れますが、これは必要な結果であると私は信じています。

于 2012-07-12T02:42:55.713 に答える