-1

文字列 (キーワード) の配列があり、より大きな文字列 (ファイルから読み取ったテキスト) 内にそれらの文字列がいくつ存在するかを確認する必要があります。大文字と小文字を区別しないチェックが必要です。現時点で私がしていることはこれです:

private void findKeywords() {
        String body = email.getMessage();
        for (String word : keywords) {
            if (body.toLowerCase().contains(word.toLowerCase())) {
                //some actions                }
            if (email.getSubject().contains(word)) {
                //some actions
            }
        }
    }

ここで質問を読むことから、別の解決策が生まれました:

private void findKeywords() {
        String body = email.getMessage();
        for (String word : keywords) {
            boolean body_match = Pattern.compile(Pattern.quote(word), Pattern.CASE_INSENSITIVE).matcher(body).find();
            boolean subject_match = Pattern.compile(Pattern.quote(word), Pattern.CASE_INSENSITIVE).matcher(email.getSubject()).find();
            if (body_match) {
                rating++;
            }
            if (subject_match) {
                rating++;
            }
        }
    }

これらのソリューションのうち、より効率的なのはどれですか? また、これを行う別の方法はありますか?受け入れられた解決策は、(上記と同等に) 実装が簡単でなければならず、できれば外部ライブラリを使用しないでください。これは、この場合はそれほど重要な問題ではないためです。

4

4 に答える 4

2

どちらのソリューションも実行可能に思えます。私が提案する改善策の 1 つは、関数をループの外に移動することです。現在のコードでは、一度だけ実行する必要がある toLowerCase() や Pattern.compile などのアクションを繰り返し実行しています。

明らかに、この問題を解決するためのはるかに高速な方法がありますが、これらの 5 行コードよりもはるかに複雑なコードが必要です。

于 2013-03-08T21:08:49.300 に答える
1

より良い:すべてのキーワードで単一のパターンを構築します。次に、そのパターンを検索します。キーワードにメタ文字(パターンで特別な意味を持つ文字)が含まれていないと仮定して、次を使用します。

StringBuilder keywordRegex = new StringBuilder();
for (String w : keywords) {
   keywordRegex.append("|"+w);
}
Pattern p = Pattern.compile(keywordRegex.substring(1));
Matcher m = new p.matcher(textToMatch);
while (m.find()) {
    // match is at m.start(); word is m.group(0);
}

すべてのキーワードを反復処理するよりもはるかに効率的です。パターンのコンパイル(1回)により、すべてのキーワードを一度に検索するオートマトンが生成されます。

于 2013-03-08T21:15:18.797 に答える
0

電子メールの本文が非常に大きい場合は、大きな文字列でtoUpperCase()を呼び出さないようにすることができるため、大文字と小文字を区別しない特殊な内容を記述することが正当化される場合があります。

static bool containsIgnoreCase(String big, String small) {
  if (small == null || big == null || small.length() > big.length()) {
    return false;
  }      
  String smallLC = small.toLowerCase();
  String smallUC = small.toUpperCase();
  for (int i = 0; i < big.length(); ++i) {
    if (matchesAt(big, i, smallLC, smallUC)) {
      return true;
    }
  }
  return false;
}

private static bool matchesAt(String big, int index, String lc, String uc) {
  if (index + lc.length() > big.length()) {
    return false;
  }
  for (int i = 0; i < lc.length(); ++i) {
    char c = big.charAt(i + index);
    if ((c != lc.charAt(i)) && (c != uc.charAt(i))) {
      return false;
    }
  }
  return true;
}
于 2013-03-08T21:28:43.247 に答える
0

あなたが言及した明示的な正規表現ソリューションは、入力文字列をメモリにコピーして文字を小文字にする toLowerCase 操作がないため、より効率的だと思います。

どちらのソリューションも実用的であり、質問はほとんどアカデミックなものですが、正規表現はよりクリーンなコードを提供すると思います。

于 2013-03-08T21:10:50.373 に答える