14

シノニムを格納するために HashMap を使用してシソーラスを作成しています。

正規表現に基づいて単語を検索しようとしています。メソッドは文字列をパラメーターとして受け取り、結果の配列を返す必要があります。ここに私の最初の刺し傷があります:

public ArrayList<String> searchDefinition(String regex) {
    ArrayList<String> results = new ArrayList<String>();

    Pattern p = Pattern.compile(regex);

    Set<String> keys = thesaurus.keySet();
    Iterator<String> ite = keys.iterator();

    while (ite.hasNext()) {
        String candidate = ite.next();
        Matcher m = p.matcher(candidate);
        System.out.println("Attempting to match: " + candidate + " to "  + regex);
        if (m.matches()) {
            System.out.println("it matches");
            results.add(candidate);
        }
    }   

    if (results.isEmpty()) {
        return null;
    }
    else {
        return results;
    }
}

さて、これは期待どおりに機能しません (または、正規表現を間違って使用している可能性があります)。ハッシュマップに次のキーがある場合:

cat, car, chopper

それから電話searchDefinition("c")するか、searchDefinition("c*")私は得るnull

  1. これを期待どおりに機能させるにはどうすればよいですか?
  2. graphシソーラスが必要とするようなものを保持するための HashMap よりも優れたデータ構造はありますか? (好奇心のみ。この課題に関しては、Java Collection Map を使用するように求められています)。
  3. 上記のコードで私が不適切に行っていることは他にありますか?

ありがとう、ダン

編集:例を修正しました。正しいケースを使用しても機能しません。

4

6 に答える 6

10

大文字と小文字を区別しないPattern.compile ( "c",Pattern.CASE_INSENSITIVE )を指定する必要があります。を含む単語を見つけるには、matcher.find()cを使用する必要があります。Matcher.matches()は、文字列全体の一致を試みます。

于 2009-05-18T21:04:53.390 に答える
9

しかし、うーん:

(a) 常に順番に検索するつもりなら、なぜ HashMap を使用するのでしょうか? これは、ハッシュキーを処理するための多くの無駄なオーバーヘッドであり、それらをまったく使用しない場合です。確かに、単純な ArrayList または LinkedList の方が良い考えです。

(b) これはシソーラスとどのような関係がありますか? なぜ正規表現を使ってシソーラスを検索するのでしょうか? たとえば、「cat」の同義語を知りたい場合は、「c.*」ではなく「cat」を検索すると思います。

シソーラスの作成方法について私が最初に考えたのは、「シノニムは同値関係ですか?」ということです。つまり、A が B のシノニムである場合、B は次のようになりますか? Aの同義語ですか?また、A が B の同義語であり、B が C の同義語である場合、A は C の同義語ですか? これらの質問に対する答えが「はい」であると仮定すると、言語内のすべての単語を同義語のセットに分割するものを構築したいので、各セット内の任意の単語をそのセット内の他のすべての単語にマッピングできます。 . したがって、必要なのは、任意の単語を取得し、それをある種のネクサス ポイントにマッピングし、そのネクサス ポイントからそれにマッピングされるすべての単語に移動する方法です。

これはデータベースでは簡単です。「word」と「token」などの 2 つの列を持つテーブルを作成し、それぞれに独自のインデックスを付けます。すべてのシノニムは同じトークンにマップされます。トークンは、シーケンス番号のように、特定のシノニムのセットに対して一意である限り、何でもかまいません。次に、指定された単語を検索し、関連するトークンを見つけて、そのトークンを持つすべての単語を取得します。たとえば、(big,1)、(large,1)、(gigantic,1)、(cat,2)、(feline,2) などでレコードを作成する場合があります。「big」を検索すると、1 が返されます。 1 を検索すると、"big"、"large"、"giant" が表示されます。

これを行う組み込みのJavaコレクションのクラスを知りません。私が考える最も簡単な方法は、2 つの調整されたハッシュ テーブルを作成することです。1 つは単語をトークンにマップし、もう 1 つはトークンを単語の配列にマップします。したがって、テーブル 1 には big->1、large->1、gigantic->1、cat->2、feline->2 などが含まれる可能性があります。次に、テーブル 2 は 1->[big,large,gigantic]、2-> をマップします。 [cat,feline] など。最初のテーブルで検索して単語をトークンにマップし、2 番目のテーブルでそのトークンを単語のリストにマップし直します。すべてのデータが冗長に保存されているため、不器用です。おそらくより良い解決策がありますが、頭から離れていません。(まあ、単語のリスト全体を毎回順番に検索すると仮定すれば簡単ですが、リストが大きくなるとパフォーマンスが低下します。)

于 2009-05-18T22:09:27.910 に答える
2

正規表現では大文字と小文字が区別されます。あなたがしたい:

Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
于 2009-05-18T21:00:10.310 に答える
2

正規表現を不適切に使用しているようです。"c" は小文字の c にのみ一致し、大文字には一致しません。

そうは言っても、全文検索機能を備えた組み込みデータベースの使用を検討することをお勧めします。

于 2009-05-18T21:03:28.650 に答える
0

上の「でもね」のジェイに応えて、

(コメントを追加したいのですが、担当者がいません。)

順番に検索するのは遅い方法です。正規表現でそれを行うことは、狂気に陥ることです。データベースでそれを行うことは、プログラミングの警官です。確かに、データ セットが大規模である場合は必要になるかもしれませんが、「この課題では、Java Collection Map を使用するように求められている」ことを思い出してください。この Java コレクションを使用する適切な方法を考え出す必要があります。

明らかでない理由は、それが 1 つのコレクションではないためです。2つです。しかし、それは 2 つのマップではありません。ArrayList ではありません。欠けているのはセットです。これは同義語のセットへのマップです。

Set<String> を使用すると、同義語のリストを作成できます。好きなだけ作ることができます。2 組の類義語が良い例です。単語を重複させたくないので、これは ArrayList ではなく Set です。

Map<String, Set<String>> を使用すると、任意の単語から類義語セットへの道をすばやく見つけることができます。

セットを構築します。次に、マップを作成します。マップとセットを取るマップを作成するヘルパー メソッドを記述します。

addSet(Map<String, Set<String>> map, Set<String> newSet)

このメソッドは単に newSet をループし、文字列をキーとしてマップに追加し、newSet への参照を値として追加します。セットごとに addSet を 1 回呼び出します。

データ構造が構築されたので、何かを見つけることができるはずです。もう少し堅牢にするために、検索する前に検索キーをきれいにすることを忘れないでください。無意味な空白を取り除くには、trim() を使用します。無意味な大文字化を取り除くには、toLowerCase() を使用します。セットを構築する前 (または構築中) に、類義語データに対してこれらの両方を実行する必要があります。それを行い、誰がこれに正規表現を必要としますか? この方法ははるかに高速で、さらに重要なことに安全です。正規表現は非常に強力ですが、問題が発生するとデバッグが困難になる可能性があります。かっこいいと思って使うのはやめましょう。

于 2013-09-14T12:10:29.333 に答える