1

私はC#で自然言語プロセッサを構築していますが、データベース内の多くの「単語」は、実際には1つの名詞またはアクションを参照する複数の単語のフレーズです。このデザインコールについての議論はありません。現時点では変更できないと言えば十分です。これらのフレーズや単語をテストする必要がある文の関連する単語(チャンク)の文字列配列があります。 サブアレイ抽出を処理してオーバーフローエラーなどのリスクを最小限に抑えるための適切な慣用的な方法は何ですか?

目的のロジックの例を示すために、サンプルチャンクを使用して実行を実行してみましょう。私たちの目的のために、データベースからの唯一の複数の単語のフレーズが「クイックブラウン」であると仮定します。

Full phrase: The quick brown fox -> encoded as {"The", "quick", "brown", "fox"}
First iteration: Test "The quick brown fox" -> returns nothing
Second iteration: Test "The quick brown" -> returns nothing
Third iteration: Test "The quick" -> returns nothing
Fourth iteration: Test "The" -> returns value
Fifth iteration: Test "quick brown fox" -> returns nothing
Sixth iteration: Test "quick brown" -> returns value
Seventh iteration: Test "fox" -> returns value

Sum all returned values and return.

私はこれをどうやって行うかについていくつかの考えを持っていますが、物事を見れば見るほど、配列アドレス指定エラーやコードを悩ませている他のそのような恐怖について本当に心配しています。フレーズは文字列配列として入力されますが、IEnumerableに配置しても問題ありません。私の唯一の懸念は、Enumerableのインデックスの欠如にあります。

4

4 に答える 4

2

これは、Aho-Corasick文字列照合アルゴリズムの完璧なアプリケーションのように聞こえます。私は短い文字列を実行する約1000万のフレーズの辞書を持っています。それは信じられないほど速いです。1回のパスで、一致するすべてのフレーズが表示されます。したがって、「the」、「fox」、および「quick brown」がすべて辞書に含まれている場合、1回のパスで3つのインデックスすべてが返されます。

実装は非常に簡単です。オンラインで元の紙を見つけて、午後に作成できます。

効率的な文字列照合:書誌検索の支援

于 2011-08-15T20:43:27.183 に答える
1

ArraySegmentまたはDelimitedArray助けますか?

于 2011-08-15T20:40:10.503 に答える
1

このようなものはどうですか:

    string[] words = new string[] { "The", "quick", "brown", "fox" };

    for (int start = 0; start < words.Length - 2; start++) // at least one word
    {
        for (int end = start + 1; end < words.Length - 1; end++)
        {
            ArraySegment<string> segment = new ArraySegment<string>(words, start, end - start);
            // test segment
        }
    }

これは、テストにArraySegmentセグメントを使用できることを前提としています。

于 2011-08-15T20:48:06.843 に答える
0

ここでの前進は、マークとフィリップの答えを組み合わせることです。理想的な状況では、私はそれを使って彼らの投稿の1つを編集したでしょうが、私の編集が拒否されたように見えます。

とにかく、私はMarkがリンクしているDelimitedArrayを取得し、その中のいくつかのことを変更しました。

コンストラクターが次のように変更されました:

    public DelimitedArray(T[] array, int offset, int count, bool throwErrors = false)
    {
        this.array = array;
        this.offset = offset;
        this.count = count;
        this.throwErrors = throwErrors;
    }

インデックス参照が次のように変更されました:

public T this[int index]
    {
        get
        {
            int idx = this.offset + index;
            if (idx > this.Count - 1 || idx < 0)
            {
                if (throwErrors == true)
                    throw new IndexOutOfRangeException("Index '" + idx + "' was outside the bounds of the array.");
                return default(T);
            }
            return this.array[idx];
        }
    }

それから私はそれをPhilippのループの使用法に取り入れました。これは次のようになります。

        for (var start = 0; start < words.Length - 2; start++) // at least one word
        {
            for (var end = start + 1; end < words.Length - 1; end++)
            {
                var segment = new DelimitedArray<string>(words, start, end - start);
                lemma = string.Join(" ", segment.GetEnumerator()); // get the word/phrase to test
                result = this.DoTheTest(lemma);

                if (result > 0)
                {
                    // Add the new result
                    ret = ret + result;

                    // Move the start sentinel up, mindful of the +1 that will happen at the end of the loop
                    start = start + segment.Count - 1;
                    // And instantly finish the end sentinel; we're done here.
                    end = words.Length;
                }
            }
        }

複数の回答を受け入れることができれば、両方の回答にマークを付けますが、両方とも不完全であるため、明日できるときに自分の回答を受け入れる必要があります。

于 2011-08-16T14:07:56.330 に答える