2009-07-11 6 views
2

C#とVB.NETの文字列処理は簡単ですが、F#で同じようにする方法を理解するのはそれほど簡単ではありません。私は2つのApress F#の本(基礎と専門家)を読んでいます。ほとんどのサンプルは数値計算であり、文字列操作はほとんどないと思います。特に、seq {配列表記}およびのサンプルはである。F#の文字列のシーケンス内の文字列をすべて検索しますか?

私はF#に変換したいC#プログラムを持っています。ここではそれが何をするかです:

  1. オープンtxtファイル
  2. 分割ファイルの段落、段落
  3. スプリット段落線の間にCRLFを探し、探し。 ! ?ラインの間
  4. 分割ライン言葉は、単語間のスペース「」のために
  5. 出力段落、行数と言葉
  6. ループ言葉、検索し、コレクション内の文字列のすべてのocurrencesを数えるのコレクションを見て、マーク見つかった単語の場所。

私はC#でできることの簡単な例ですが、まだF#ではありません。

これはテキストファイルであると仮定します。

受注、2008年3月18日、 、入力された最高裁判所、ニューヨーク州 (ポール・Gの誰か)に持続的な個人 傷害のためのアクションでおり、 が早すぎるとして、拒否された、から訴え限りにおいて、伝えられるところで によって被告の市や 連結マクファーソンの過失、および その請負業者(Mallen)に対する連結McPhersonのサードパーティ アクションを作成したポットホールの上に を旅し、秋、 要約のためのMallenの動き 苦情を解消し、 サードパーティの苦情を全会一致で 、費用なしで確認しました。

当事者は、他に規定又は により、裁判所を通じて手続きコース をチャートに大きな自由度を与えています。したがって、 Mallenは遅れて 提出の口実を提示していないので、Mallenの動きの否定的なものとして の否定を確認します。

私はこの出力を得る:

2 Paragraphs 
3 Lines 
109 Words 

Found Tokens: 2 
Token insofar: ocurrence(s) 1: position(s): 52 
Token thus: ocurrence(s) 1: position(s): 91 

行は文と呼ばれている必要があります:(

いくつかのトークンがあり、私はクラスごとにグループ化され、100以上を言うだろう、私は反復しなければなりません。同じ文章で複数回トークンをマッチさせようとしています。ここでは、文章をどのように分割してListBoxに入れるかを簡単に示しています。そして、私がどのようにしてforeachに頼っているかを示しています。私が避けたいこのアプローチですg可能であればseq {シーケンス式}とseq.iterまたはList.iterと一致するトークンをすべてリストします。それが必要です。

/// <summary> 
    /// split the text into sentences and displays 
    /// the results in a list box 
    /// </summary> 
    private void btnParseText_Click(object sender, EventArgs e) 
    { 
     lstLines.Items.Clear(); 

     ArrayList al = SplitLines(richTextBoxParagraphs.Text); 
     for (int i = 0; i < al.Count; i++) 
      //populate a list box 
      lstLines.Items.Add(al[i].ToString()); 
    } 


    /// <summary> 
    /// parse a body of text into sentences 
    /// </summary> 
    private ArrayList SplitLines(string sText) 
    { 

     // array list tto hold the sentences 
     ArrayList al = new ArrayList(); 

     // split the lines regexp 
     string[] splitLines = 
      Regex.Split(sText, @"(?<=['""A-Za-z0-9][\.\!\?])\s+(?=[A-Z])"); 

     // loop the sentences 
     for (int i = 0; i < splitLines.Length; i++) 
     { 
      string sOneLine = 
       splitLines[i].Replace(Environment.NewLine, string.Empty); 
      al.Add(sOneLine.Trim()); 
     } 

     // update statistics 
     lblLineCount.Text = "Line Count: " + 
      GetLineCount(splitLines).ToString(); 
     // words 
     lblWordCount.Text = "Word Count: " + 
      GetWordCount(al).ToString(); 
     // tokens 
     lblTokenCount.Text = "Token Count: " + 
      GetTokenCount(al).ToString(); 

     // return the arraylist 
     return al; 
    } 

    /// <summary> 
    /// count of all words contained in the ArrayList 
    /// </summary> 
    public int GetWordCount(ArrayList allLines) 
    { 
     // return value 
     int rtn = 0; 

     // iterate through list 
     foreach (string sLine in allLines) 
     { 
      // empty space is the split char 
      char[] arrSplitChars = {' '}; 

      // create a string array and populate 
      string[] arrWords = sSentence.Split(arrSplitChars, StringSplitOptions.RemoveEmptyEntries); 
      rtn += arrWords.Length; 
     } 

     // return word count 
     return rtn; 
    } 

実際、これは非常に単純なWindowsアプリケーションです。 1つのRichTextBoxと3つのListBox(段落、行、トークンが見つかりました)、出力を表示するラベル、および1つのボタンを持つフォーム。

答えて

5

ブライアンは良いスタートを持っていますが、機能コードは、「方法」よりも何をしようとしているのですか。

私たちは似た同様にして起動することができます。

open System 
open System.Text.RegularExpressions 

let text = @"Order, Supreme Court, New York County (Paul G Someone), entered..." 

let lines = text.Split([|Environment.NewLine|], StringSplitOptions.None) 

まずは、段落を見てみましょう。段落を区切る空白行を数えるブライアンのアプローチが好きです。

let numParagraphs = 
    let blankLines = lines |> Seq.filter (fun line -> Regex.IsMatch(line, @"^\s*$")) 
          |> Seq.length 
    blankLines + 1 

文章については、我々は文字のシーケンスとしてフルテキストを表示し、sentence-の数を数えることができます。だから我々はそれらを数え、唯一の空白行を見つけるためにフィルタリングし、その値に基づいて、当社の段落の数を返します終了文字。それはF#のだから、のは、パターンマッチングを使用してみましょう:

let numSentences = 
    let isSentenceEndChar c = match c with 
           | '.' | '!' | '?' -> true 
           | _ -> false 
    text |> Seq.filter isSentenceEndChar 
     |> Seq.length 

マッチング言葉は単純な正規表現と同じくらい簡単にすることができますが、句読点を処理する方法を変化させることができる:

let words = Regex.Split(text, "\s+") 
let numWords = words.Length 

numParagraphs |> printfn "%d paragraphs" 
numSentences |> printfn "%d sentences" 
numWords  |> printfn "%d words" 

は最後に、我々は定義このコードは、「これ」、その末尾のコンマのを見つけないことを

let findToken token = 
    let tokenMatch (word : string) = word.Equals(token, StringComparison.OrdinalIgnoreCase) 
    words |> Seq.iteri (fun n word -> 
     if tokenMatch word then 
      printfn "Found %s at word %d" word n 
    ) 

let tokensToFind = ["insofar"; "thus"; "the"] 
tokensToFind |> Seq.iter findToken 

注:簡単にトークンのリストに適用されるトークンの出現箇所を、印刷する機能。 wordsがどのように生成されるか、tokenMatchがどのように定義されるかを調整したいと思うでしょう。

0

C#-programを投稿できますか?

私は、元のコードが変数の変更に大きく依存していない限り(これはあなたの問題の説明に理由がないと思われます)、F#で非常によく似た方法で実装できます。

はケースでは、C#でString.Splitを使用:それは基本的には同じことだ:結果のシーケンスを連結するために

open System 
let results = "Hello World".Split [|' '|] 
let results2 = "Hello, World".Split ([| ", "|], StringSplitOptions.None) 

、あなたはyieldyield!を組み合わせることができます。

抽象例

let list = [ yield! [1..8]; for i in 3..10 do yield i * i ] 
+0

よく、はい、分割は同じです。私もregexpを使います。私がわからないことは、段落、行、言葉をどのようにシーケンスに入れるかということです。私はList.iterとseqのサンプルを読みました。iterと私は数字のためにそれを得るが、文字列のためではない。 C#では、ArrayListにすべてを入れて、段落内のforeach段落にあまりにも多く頼っています... foreach line in lines ... foreach word in words ...、そしてトークンのコレクションがあります。 F#でシーケンスやリストを使用して簡単に行う方法は、現在のソリューションの命令的なスタイルを模倣しないようにする必要があります。 – dde

+0

これはF#のリストジェネレータ構文で表現できます。編集私のポスト – Dario

1

あなたは(質問であなたのC#コードをポストあなたはすでに一つの言語での努力を行ってきた実証し、実際にある場合には宿題のようなビットは、人々がより多くの信仰を持って聞こえるはずです別のものについてもっと学びたい)。

ここでは必ずしもF#固有のものはありませんが、これは.Net言語でも同様にすることができます。いくつかの戦略があります。たとえば以下のように、正規表現を使って単語をレキシングします。ただし、以下の2つのF#イディオムだけです。

open System 
open System.Text.RegularExpressions 

let text = @"Order, Supreme Court, New York County (Paul G Someone), entered 
March 18, 2008, which, in an action for personal injuries sustained in a 
trip and fall over a pothole allegedly created by the negligence of 
defendants City or Consolidated McPherson, and a third-party action by 
Consolidated McPherson against its contractor (Mallen), insofar as appealed 
from, denied, as untimely, Mallen's motion for summary judgment dismissing 
the complaint and third-party complaint, unanimously affirmed, without costs. 

Parties are afforded great latitude in charting their procedural course 
through the courts, by stipulation or otherwise. Thus, we affirm the denial 
of Mallen's motion as untimely since Mallen offered no excuse for the late 
filing." 

let lines = text.Split([|'\n'|]) 
// If was in file, could use 
//let lines = System.IO.File.ReadAllLines(@"c:\path\filename.txt") 
// just like C#. For this example, assume have giant string above 

let fullText = String.Join(" ", lines) 
let numParagraphs = 
    let mutable count = 1 
    for line in lines do 
     // look for blank lines, assume each delimits another paragraph 
     if Regex.IsMatch(line, @"^\s*$") then 
      count <- count + 1 
    count 
let numSentences =  
    let mutable count = 1 
    for c in fullText do 
     if c = '.' || c = '!' || c = '?' then 
      count <- count + 1 
    count 
let words = 
    let wordRegex = new Regex(@"\b(\w+)\b") 
    let fullText = String.Join(" ", lines) 
    [| for m in wordRegex.Matches(fullText) do 
     yield m.Value |] 
printfn "%d paragraphs" numParagraphs 
printfn "%d sentences" numSentences 
printfn "%d words" words.Length 
let Find token = 
    words |> Seq.iteri (fun n word -> 
     if 0=String.Compare(word, token, 
          StringComparison.OrdinalIgnoreCase) then 
      printfn "Found %s at word %d" word n 
    ) 
let tokensToFind = ["insofar"; "thus"; "the"] 
for token in tokensToFind do 
    Find token 
+0

AAAAAAArh - 不必要な変更可能な値! 機能するには、再帰的なCount関数を使用して置き換えます。 – Dario

+0

Darioが動作します。私が書いていることを考えてみましょう。「ほとんどのサンプルは数値計算であり、文字列操作はほとんどありません」... seqとリストを使った文字列操作に関する例はほとんどありません。私の発展の大部分は文字列操作に関連しているため、私は不満を抱いています。構文解析、意味解析...そしてもう少しサンプルがあります。私はF#の初心者ですが、LexingとParsingに関する書籍の章は今はあまりにも多くあります。驚くべきブライアン(あなたと、F#でのコーディングがいかに少ないか)。本当にありがとう。 – dde

関連する問題