2013-05-05 14 views
7

文字列内の特定の位置の単語を取得したいと考えています。たとえば、2ワード後、2ワード前など。例えば文字列内の位置を囲む単語を取得する

は、文字列を考えてみます。

String str = "Hello my name is John and I like to go fishing and hiking I have two sisters and one brother."; 
String find = "I"; 

for (int index = str.indexOf("I"); index >= 0; index = str.indexOf("I", index + 1)) 
{ 
    System.out.println(index); 
} 

これは言葉は「私は」であるところのインデックスを書き出します。しかし、私はこれらの位置の周りに単語の部分文字列を得ることができるようにしたい。

私は「ジョンと私が好き」と「ハイキングしているのは2つ」を印刷できるようにしたい。

単一の単語列を選択できるだけでなく、 "John and"を検索すると "name is John and I like"が返されます。

これを行うためのすてきでスマートな方法はありますか?

+0

どのようにして、周囲の言葉を決定するのですか? –

+0

はい、それは問題です、どのように正確に2単語前と2単語後が部分文字列になるようにstartPosを取得するのですか? – user1506145

答えて

10

シングル単語:

あなたはString's split() methodを使用していることachiveveことができます。この解は、O(n)です。

public static void main(String[] args) { 
    String str = "Hello my name is John and I like to go fishing and "+ 
         "hiking I have two sisters and one brother."; 
    String find = "I"; 

    String[] sp = str.split(" +"); // "+" for multiple spaces 
    for (int i = 2; i < sp.length; i++) { 
     if (sp[i].equals(find)) { 
      // have to check for ArrayIndexOutOfBoundsException 
      String surr = (i-2 > 0 ? sp[i-2]+" " : "") + 
          (i-1 > 0 ? sp[i-1]+" " : "") + 
          sp[i] + 
          (i+1 < sp.length ? " "+sp[i+1] : "") + 
          (i+2 < sp.length ? " "+sp[i+2] : ""); 
      System.out.println(surr); 
     } 
    } 
} 

出力:

John and I like to 
and hiking I have two 

マルチ語:

正規表現findが複数の単語であるときの場合のための偉大な、きれいなソリューションです。しかし、その性質上、の単語もfindと一致するケースがありません(以下の例を参照)。

以下のアルゴリズムはすべてのケース(すべての解のスペース)を処理します。問題の性質のために、最悪の場合には、この溶液は、O(N×m個)nがS長strfindあるの長さとm」である)である、ということに注意してください。

public static void main(String[] args) { 
    String str = "Hello my name is John and John and I like to go..."; 
    String find = "John and"; 

    String[] sp = str.split(" +"); // "+" for multiple spaces 

    String[] spMulti = find.split(" +"); // "+" for multiple spaces 
    for (int i = 2; i < sp.length; i++) { 
     int j = 0; 
     while (j < spMulti.length && i+j < sp.length 
            && sp[i+j].equals(spMulti[j])) { 
      j++; 
     }   
     if (j == spMulti.length) { // found spMulti entirely 
      StringBuilder surr = new StringBuilder(); 
      if (i-2 > 0){ surr.append(sp[i-2]); surr.append(" "); } 
      if (i-1 > 0){ surr.append(sp[i-1]); surr.append(" "); } 
      for (int k = 0; k < spMulti.length; k++) { 
       if (k > 0){ surr.append(" "); } 
       surr.append(sp[i+k]); 
      } 
      if (i+spMulti.length < sp.length) { 
       surr.append(" "); 
       surr.append(sp[i+spMulti.length]); 
      } 
      if (i+spMulti.length+1 < sp.length) { 
       surr.append(" "); 
       surr.append(sp[i+spMulti.length+1]); 
      } 
      System.out.println(surr.toString()); 
     } 
    } 
} 

は出力:

name is John and John and 
John and John and I like 
+3

+1 ..素敵な答え:) – Maroun

+1

indexOfが使われていない場合は、ありがとうございます。しかし、複数単語の文字列を検索することはできません。 – user1506145

+0

+1周囲のロジック – exexzian

1

利用のstring.Split()の言葉にテキストを分割します。そして、「I」を検索して、一緒に戻って単語を連結します。

String[] parts=str.split(" "); 

for (int i=0; i< parts.length; i++){ 
    if(parts[i].equals("I")){ 
    String out= parts[i-2]+" "+parts[i-1]+ " "+ parts[i]+ " "+parts[i+1] etc.. 
    } 
} 

は勿論あなたは、I-2が有効なインデックスであり、そしてあなたはたくさんのを持っている場合のStringBufferを使用すると、便利なパフォーマンスが賢明だろうかどうかを確認する必要がありますデータ...

1
// Convert sentence to ArrayList 
String[] stringArray = sentence.split(" "); 
List<String> stringList = Arrays.asList(stringArray); 

// Which word should be matched? 
String toMatch = "I"; 

// How much words before and after do you want? 
int before = 2; 
int after = 2; 

for (int i = 0; i < stringList.size(); ++i) { 
    if (toMatch.equals(stringList.get(i))) { 
     int index = i; 
     if (0 <= index - before && index + after <= stringList.size()) { 
      StringBuilder sb = new StringBuilder(); 

      for (int i = index - before; i <= index + after; ++i) { 
       sb.append(stringList.get(i)); 
       sb.append(" "); 
      } 
      String result = sb.toString().trim(); 
      //Do something with result 
     } 
    } 
} 

これは、マッチの前と後の2つの単語を抽出します。 を最大での2ワード前に印刷し、を正確にの2ワードとすることはできません。

EDIT遅くするための方法および無空想三項演算子:/

2

ここでは、私は正規表現を使用して見つけたもう一つの方法である:

 String str = "Hello my name is John and I like to go fishing and hiking I have two sisters and one brother."; 

     String find = "I"; 

     Pattern pattern = Pattern.compile("([^\\s]+\\s+[^\\s]+)\\s+"+find+"\\s+([^\\s]+\\s[^\\s]+\\s+)"); 
     Matcher matcher = pattern.matcher(str); 

     while (matcher.find()) 
     { 
      System.out.println(matcher.group(1)); 
      System.out.println(matcher.group(2)); 
     } 

出力:

John and 
like to 
and hiking 
have two 
+0

パーフェクト!今では、複数単語の文字列を検索することもできます。 – user1506145

+0

Great :) '\\ s +'で正規表現を更新し、複数のスペースを扱う必要があります。 – Vishy

0
public static void main(String[] args) { 
    String str = "Hello my name is John and I like to go fishing and hiking I have two sisters and one brother."; 
    String find = "I"; 
    int countWords = 3; 
    List<String> strings = countWordsBeforeAndAfter(str, find, countWords); 
    strings.stream().forEach(System.out::println); 
} 

public static List<String> countWordsBeforeAndAfter(String paragraph, String search, int countWordsBeforeAndAfter){ 
    List<String> searchList = new ArrayList<>(); 
    String str = paragraph; 
    String find = search; 
    int countWords = countWordsBeforeAndAfter; 
    String[] sp = str.split(" +"); // "+" for multiple spaces 
    for (int i = 0; i < sp.length; i++) { 
     if (sp[i].equals(find)) { 

      String before = ""; 
      for (int j = countWords; j > 0; j--) { 
       if(i-j >= 0) before += sp[i-j]+" "; 
      } 

      String after = ""; 
      for (int j = 1; j <= countWords; j++) { 
       if(i+j < sp.length) after += " " + sp[i+j]; 
      } 
      String searhResult = before + find + after; 
      searchList.add(searhResult); 
     } 
    } 
    return searchList; 
} 
関連する問題