2009-05-09 16 views
1

テキストのブロックにすべての可能なフレーズを作成するアルゴリズムが必要です。たとえば、テキストで:単語のテキストを分析するアルゴリズム

"My username is click upvote. I have 4k rep on stackoverflow" 

それは以下の組み合わせを作成します。

"My username" 
"My Username is" 
"username is click" 
"is click" 
"is click upvote" 
"click upvote" 
"i have" 
"i have 4k" 
"have 4k" 
.. 

あなたがアイデアを得ます。基本的には、「文句」のすべての可能な組み合わせを文の中から得ることです。これを最もうまく実装する方法についての考えはありますか?

+0

しかし、これらのフレーズはどのようなルールで作成されていますか? – Gumbo

+0

それを見て、それは2〜3の連続した言葉です... – Tomalak

+11

自然言語処理==痛みの世界 – Greg

答えて

5

基本的に、文章のブロックを文章に分割する必要があります。それは、あなたがピリオド、疑問符、感嘆符、および他の文章の終端記号を調べる必要があるので、英語でさえ十分に扱いにくいです。

次に、すべての句読点(カンマ、セミコロン、コロンなど)を削除した後、一度に1つの文を処理します。

あなたは、単語の配列が残っているときに、それが簡単になる:

for i = 1 to num_words-1: 
    for j = i+1 to num_words: 
     phrase = words[i through j inclusive] 
     store phrase 

それだ、非常にシンプル(は同じくらい簡単ではないかもしれないテキストブロックの最初のマッサージの後あなたが考えるように)。

これは、すべての文章で2つ以上の単語のすべてのフレーズを提供します。

文章の分離、単語の分離、句読点の削除などは最も難しいでしょうが、私はあなたにいくつかの簡単な初期規則を示しました。残りの部分は、テキストのブロックがアルゴリズムを壊すたびに追加する必要があります。

更新:

public class testme { 
    public final static String text = 
     "My username is click upvote." + 
     " I have 4k rep on stackoverflow."; 

 

public static void procSentence (String sent) { 
     System.out.println ("=========="); 
     System.out.println ("sentence [" + sent + "]"); 

     // Split sentence at whitspace into array. 

     String [] sa = sent.split("\\s+"); 

     // Process each starting word. 

     for (int i = 0; i < sa.length - 1; i++) { 

      // Process each phrase. 

      for (int j = i+1; j < sa.length; j++) { 

       // Build the phrase. 

       String phrase = sa[i]; 
       for (int k = i+1; k <= j; k++) { 
        phrase = phrase + " " + sa[k]; 
       } 

       // This is where you have your phrase. I just 
       // print it out but you can do whatever you 
       // wish with it. 
       System.out.println (" " + phrase); 
      } 
     } 
    } 

 

public static void main(String[] args) { 
     // This is the block of text to process. 

     String block = text; 
     System.out.println ("block [" + block + "]"); 

     // Keep going until no more sentences. 

     while (!block.equals("")) { 
      // Remove leading spaces. 

      if (block.startsWith(" ")) { 
       block = block.substring(1); 
       continue; 
      } 

      // Find end of sentence. 

      int pos = block.indexOf('.'); 

      // Extract sentence and remove it from text block. 

      String sentence = block.substring(0,pos); 
      block = block.substring(pos+1); 

      // Process the sentence (this is the "meat"). 

      procSentence (sentence); 

      System.out.println ("block [" + block + "]"); 
     } 
     System.out.println ("=========="); 
    } 
} 
:要求され、ここでフレーズを与えるいくつかのJavaコードだとして

出力

block [My username is click upvote. I have 4k rep on stackoverflow.] 
========== 
sentence [My username is click upvote] 
    My username 
    My username is 
    My username is click 
    My username is click upvote 
    username is 
    username is click 
    username is click upvote 
    is click 
    is click upvote 
    click upvote 
block [ I have 4k rep on stackoverflow.] 
========== 
sentence [I have 4k rep on stackoverflow] 
    I have 
    I have 4k 
    I have 4k rep 
    I have 4k rep on 
    I have 4k rep on stackoverflow 
    have 4k 
    have 4k rep 
    have 4k rep on 
    have 4k rep on stackoverflow 
    4k rep 
    4k rep on 
    4k rep on stackoverflow 
    rep on 
    rep on stackoverflow 
    on stackoverflow 
block [] 
========== 

、これはJavaのかなり基本的で心に留めておくには、(いくつかは、それがC :-)のJava方言で書かれていると言うかもしれません。あなたが尋ねたように文から単語群を出力する方法を説明することを意味しています。

ありますではありません私は元の答えで言及したすべての上質な文章の検出と句読点除去を行います。

+0

forループの例のようにphp/c/javaを付けることはできますか?私は文法に慣れていないので、それが何をしているのか理解できません。素敵なコードをjavaに表示することができたら、 –

5

まあ、PHPやjavaは分かりませんが、基本的にはテキストのすべての単語に対してダブルループが必要です。ここではいくつかの擬似コードです:第二のループは、私から開始していない1.これはあなたのワード数から始まるすべてのフレーズを与えること

words = split(text) 
n = len(words) 
for i in 1...n-1 {  // i = first word in phrase 
    for j in i+1...n {  // j = last word in phrase 
     phrase = join(words[i:j]) 
     print phrase 
    } 
} 

注大きい単語番号j、iにI(ので、すべてのフレーズより少なくとも2つの単語を持つ)。

ああ、おそらく文章の境界を越えるフレーズを望まないと思っただけです。だから、文を最初に文に分割する外側のループが必要ですが、各文でこれを実行します。

プログラミングの経験があればこのようになりますが、forの文はループ[for(i=1; i<=n; i++)]のようになります。splitは文字列を取り、単語の配列に分割する関数です。これは完全に自明ではありませんが、おそらくこれを行うライブラリ関数があります。lenは配列の長さを返します。joinはそれらをスペースで置き換えます。[i:j]は、iからjまでのすべての要素を意味しますこれは実際には[i:j+1]です)。ああ、私は暗黙のうちに、配列は0ではなくインデックス1から始まると仮定しています。私は

最後に、特定の質問に答えるために...運動として0ベースのC配列に変更したまま:「第二」のループが実際にインナーループであることを

  • は注意を。 i(フレーズの最初の単語)の各値に対して、i+1からフレーズの最後の単語を与えるためにセンテンスの最後までループします。

  • 最初の単語と最後の単語の番号があるので、書かなければならないjoin関数は、個々の文字列word[i], word[i+1], ... word[j]を連結してフレーズを構成します。実際には、これは関数がjoin(words, i, j)のように宣言され、文字列を返しますが、これを簡単にする方法がいくつかあります。

+0

コードをJavaに翻訳できますか? –

+4

最初の文章を読むと、彼はPHPやJavaを知らないことがわかります。さらに、与えられた擬似コードは、基本的なJavaの知識と少しの検索があれば、Javaに翻訳するのに十分シンプルでなければなりません。 –

+0

私は擬似コードを理解できれば、それは私にはほとんど意味がありません。彼は自分のタグの1つとしてJavaを持っています。 –

2

文章をトークン化して、CombinationGeneratorを使用します。このアルゴリズムは、Kenneth H.Rosen、Discrete Mathematics and Its Applications、第2版(NY:McGraw-Hill、1991)、pp.284-286に記載されている。ここで

は、使用のコードと例です: http://www.merriampark.com/comb.htm

+0

もう一度(ジェスの試行のように)、すべての可能な組み合わせを望むわけではありません。これははるかに簡単な問題です(2,3回以上解決しました)! –

+0

ああ...今私は参照してください。 – Cuga

1

str_word_count();で再生すると、あなたが好きなようにそれを構築することができます。

1

このようなフレーズの専門用語はShingleです。 LuceneのShingeMatrixFilterで入力テキストの対象物を取得できます。

+0

ShingleMatrixFilterはすでに廃止されており、4.0で削除される予定です。代わりにShingleFilterの使用を検討することをお勧めします。 –

関連する問題