正規表現でのアクティブパターンの使用に関するこの便利な記事を見つけました:http: //www.markhneedham.com/blog/2009/05/10/f-regular-expressionsactive-patterns/
この記事で使用された元のコードスニペットは次のとおりです。
open System.Text.RegularExpressions
let (|Match|_|) pattern input =
let m = Regex.Match(input, pattern) in
if m.Success then Some (List.tl [ for g in m.Groups -> g.Value ]) else None
let ContainsUrl value =
match value with
| Match "(http:\/\/\S+)" result -> Some(result.Head)
| _ -> None
これにより、少なくとも1つのURLが見つかったかどうか、およびそのURLが何であったかがわかります(スニペットを正しく理解している場合)
次に、コメントセクションで、ジョエルはこの変更を提案しました。
別の方法として、特定のグループが一致する場合とそうでない場合があるため、次のようになります。
List.tail [ for g in m.Groups -> if g.Success then Some g.Value else None ]
または、グループにラベルを付けて、名前でアクセスしたい場合もあります。
(re.GetGroupNames() |> Seq.map (fun n -> (n, m.Groups.[n])) |> Seq.filter (fun (n, g) -> g.Success) |> Seq.map (fun (n, g) -> (n, g.Value)) |> Map.ofSeq)
これらすべてを組み合わせようとした後、私は次のコードを思いつきました。
let testString = "http://www.bob.com http://www.b.com http://www.bob.com http://www.bill.com"
let (|Match|_|) pattern input =
let re = new Regex(pattern)
let m = re.Match(input) in
if m.Success then Some ((re.GetGroupNames()
|> Seq.map (fun n -> (n, m.Groups.[n]))
|> Seq.filter (fun (n, g) -> g.Success)
|> Seq.map (fun (n, g) -> (n, g.Value))
|> Map.ofSeq)) else None
let GroupMatches stringToSearch =
match stringToSearch with
| Match "(http:\/\/\S+)" result -> printfn "%A" result
| _ -> ()
GroupMatches testString;;
インタラクティブセッションでコードを実行すると、次のように出力されます。
map [("0", "http://www.bob.com"); ("1", "http://www.bob.com")]
私が達成しようとしている結果は、次のようになります。
map [("http://www.bob.com", 2); ("http://www.b.com", 1); ("http://www.bill.com", 1);]
基本的に、見つかった各一意の一致のマッピングと、それに続く特定の一致する文字列がテキストで見つかった回数のカウント。
私がここで間違った道を進んでいると思われる場合は、まったく別のアプローチを提案してください。私はアクティブパターンと正規表現の両方に少し慣れていないので、これを修正するためにどこから始めればよいのかさえわかりません。
また、これは基本的にC#でF#に変換して行うことです。
let testString = "http://www.bob.com http://www.b.com http://www.bob.com http://www.bill.com"
let matches =
let matchDictionary = new Dictionary<string,int>()
for mtch in (Regex.Matches(testString, "(http:\/\/\S+)")) do
for m in mtch.Captures do
if(matchDictionary.ContainsKey(m.Value)) then
matchDictionary.Item(m.Value) <- matchDictionary.Item(m.Value) + 1
else
matchDictionary.Add(m.Value, 1)
matchDictionary
これは実行時にこれを返します:
val matches : Dictionary = dict [("http://www.bob.com", 2); ("http://www.b.com", 1); ("http://www.bill.com", 1)]
これは基本的に私が探している結果ですが、これを行うための機能的な方法を学ぼうとしているので、アクティブなパターンを含める必要があると思います。私の最初の試みよりも理にかなっている場合は、これを「機能化」してみてください。
前もって感謝します、
ボブ