0

私は現在、テキストファイル内の関連する用語/単語の検索を扱う小さなC#演習を行っています。プログラムは、検索された単語を含むテキストファイル内のすべての文を書き出します。たとえば、「example」という単語を入力すると、プログラムはテキストファイル内のすべての文を調べて、「example」という単語が含まれている文を引き出します。

The text file is structured as so: <sentenceDesignator> <text>
sentence 1: bla bla bla bla example of a sentence  //each line contains a sentence
sentence 2: this is not a good example of grammar
sentence 3: bla is not a real word, use better terms

私ができるようにしたいのは、線形検索を使用してテキストファイルのすべての行を調べ、検索された文字列用語を含むすべての文を書き出すことです。

これまでの私のコード:

        String filename = @"sentences.txt";

        if (!File.Exists(filename))
        {
            // Since we just created the file, this shouldn't happen.
            Console.WriteLine("{0} not found", filename);
            return;
        }
        else
        {
            Console.WriteLine("Successfully found {0}.", filename);
        }
        //making a listof type "Sentence" to hold all the sentences
        List<Sentence> sentences = new List<Sentence>();

        //the next lines of code...
        StreamReader reader = File.OpenText(filename);

        //first, write out all of the sentences in the text file

        //read a line(sentence) from a line in the text file
        string line = reader.ReadLine();

        while (line != null)
        {
            Sentence s = new Sentence();

            //we need something to split data...
            string[] lineArray = line.Split(':');

            s.sentenceDesignator = lineArray[0];
            s.Text = lineArray[1];

            Console.Write("\n{0}", line);

            line = reader.ReadLine();
        }

        //so far, we can write out all of the sentences in the text file. 
        Console.Write("\n\nOK!, search a term to diplay all their occurences: ");
        string searchTerm = Console.ReadLine();

       if(!line.Contains(searchterm))
       {
          Console.Write("\nThat term does not exist in any sentence.");
       }
       else
        {
            foreach (Sentence ss in sentences)
            {
                if (ss.sentenceDesignator.Contains(queryName))
                {
                    //I need help here
                }
            }
        }
4

2 に答える 2

1

線形検索の場合と同様に、ファイルのインデックスを作成してからインデックスを検索すると、すべての検索操作が高速になりますがO(n)、インデックス付き検索の場合O(n)は、インデックスの作成用ですがO(log n)near-O(1)ルックアップ用です(作成方法によって異なります)。あなたのインデックス)。コストはインデックスのメモリ消費量の増加ですが、私は次のようにします。

private Dictionary<String,List<Int32>> _index = new Dictionary<String,List<Int32>>();

/// <summary>Populates an index of words in a text file. Takes O(n) where n is the size of the input text file.</summary>
public void BuildIndex(String fileName) {

    using(Stream inputTextFile = OpenFile(...)) {

        int currentPosition = 0;
        foreach(String word in GetWords(inputTextFile)) {

            word = word.ToUpperInvariant();
            if( !_index.ContainsKey( word ) ) _index.Add( word, new List<Int32>() );
            _index[word].Add( currentPosition );

            currentPosition = inputTextFile.Position;
        }
    }
}

/// <summary>Searches the text file (via its index) if the specified string (in its entirety) exists in the document. If so, it returns the position in the document where the string starts. Otherwise it returns -1. Lookup time is O(1) on the size of the input text file, and O(n) for the length of the query string.</summary>
public Int32 SearchIndex(String query) {

    String[] terms = query.Split(' ');

    Int32 startingPosition = -1;
    Int32 currentPosition = -1;
    Boolean first = true;
    foreach(String term in terms) {
        term = term.ToUpperInvariant();

        if( first ) {
            if( !_index.Contains( term ) ) return -1;
            startingPosition = _index[term][0];
        } else {

            if( !ContainsTerm( term, ++currentPosition ) ) return -1;
        }

        first = false;
    }

    return startingPosition;
}

/// <summary>Indicates if the specified term exists at the specified position.</summary>
private Boolean ContainsTerm(String term, Int32 expectedPosition) {

    if( !_index.ContainsKey(term) ) return false;
    List<Int32> positions = _index[term];
    foreach(Int32 pos in positions) {

        if( pos == expectedPosition ) return true;
    }
    return false;
}

OpenFileとの実装はGetWords簡単なはずです。GetWordsを使用して、ファイル内に空白で区切られた単語をyield return作成IEnumerable<String>したり、カスタムファイル形式を処理したりすることに注意してください。

于 2013-02-25T07:05:30.570 に答える
0

最後のif/elseについて少し混乱しています。ファイルの最後の行を検索語と比較しているだけのようです。また、「queryName」はどこから来たのですか?そして、あなたは全文(「文のbla bla bla blaの例」)を印刷したいですか、それとも単に「文1」を印刷したいですか?また、sentenceDesignatorにqueryNameが含まれているかどうかを確認します。実際のテキストに、searchtermが含まれているかどうかを確認したいと思いました。

多分これはあなたを助けるでしょう:

var lines = File.ReadAllLines(fileName);    
var sentences = new List<Sentence>(lines.Count());

foreach (var line in lines)
{
    var lineArray = line.Split(':');
    sentences.Add(new Sentence { sentenceDesignator = lineArray[0], Text = lineArray[1]});
}

foreach (var sentence in sentences)
{
    if (sentence.Text.Contains(searchTerm))
    {
        Console.WriteLine(sentence.sentenceDesignator);
        //Console.WriteLine(sentence.Text);
    }
}
于 2013-02-25T09:25:04.080 に答える