1

私はプログラミング自体と C# winforms に非常に慣れていないので、ご容赦ください。

AAA.txtコンボボックスに「AAA」として表示するファイルがあります。私の主な意図は、ユーザーがドロップダウン コンボから AAA を選択し、検索をクリックできるようにすることです。<description></description>クリック イベントで、関数はテキスト ファイルのコンテンツを 1 行ずつ読み取り、20 個の XML ファイルのすべての子ノードにこれらの単語 (hello など) またはフレーズ (おはようなど) が含まれているかどうかを確認します。これらの単語/フレーズが特定の子ノードに表示される場合、親ノード<description></description>全体のデータが結果として表示されます。<item></item>

AAA.txt:

hello
good morning
great
bye

私の機能:

private void searchComByKeywords()
{ 
    string[] fileEntries = Directory.GetFiles(sourceDir);
    foreach (string fileName in fileEntries)
    {
        XmlDocument xmlDoc = new XmlDocument();
        string docPath = fileName;
        xmlDoc.Load(docPath);
        XmlNodeList nodeList = xmlDoc.GetElementsByTagName("item");

        foreach (XmlNode node in nodeList)
        {
            XmlElement itemElement = (XmlElement)node;
            string itemDescription = itemElement.GetElementsByTagName("description")[0].InnerText;

            if (itemDescription.ToLower().Contains(comboTemplates.SelectedItem.ToString()))
            {
                string itemTitle = itemElement.GetElementsByTagName("title")[0].InnerText;
                string itemDate = itemElement.GetElementsByTagName("pubDate")[0].InnerText;
                string itemAuthor = itemElement.GetElementsByTagName("author")[0].InnerText;

                richComByTemplate.AppendText("Author: " + itemAuthor + "\nDate: " + itemDate + "\nTitle: " + itemTitle + "\nDescription: " + itemDescription + "\n\n--------\n\n");
            }
        }
    }
}

LINQ-to-XML を使用するように言われる人もいるかもしれませんが、現時点ではこれは問題ではありません。私は、この行が意図したとおりにif (itemDescription.ToLower().Contains(comboTemplates.SelectedItem.ToString()))機能しないことを知っています (選択した AAA テキスト ファイルを調べる代わりに、「AAA」という単語を検索します)。選択したテキスト ファイルに表示される単語/フレーズを読み取るために、この行を正しく記述する方法を教えてください。

ありがとうございました。

4

1 に答える 1

2

静的System.IO.FileクラスにはReadAllLines、テキスト ファイルのすべての行を配列に読み込むメソッドがあります。

string[] words = File.ReadAllLines(filepath);

コンボにファイル名のみが含まれている場合は、最初にディレクトリ名を追加することをお勧めします

string dir = @"C:\MyDataPath";
string filename = comboTemplates.SelectedItem.ToString();
string filepath = Path.Combine(dir, filename);

次に、単語をHashSet<string>

var wordSet = new HashSet<string>(words);

次に、正規表現を使用して説明を 1 つの単語に分割します

var descrWords = 
    new HashSet<string>(
        Regex.Matches(itemDescription.ToLower(), @"\w+")
        .Cast<Match>()
        .Select(m => m.Value)
    );
descrWords.UnionWith(wordSet);
if (descrWords.Count > 0) {
    // Your description contains at least one of the words
}

さまざまな方法で比較を行うことができます。たとえば、LINQ を使用して

if (words.Union(
    Regex.Matches(itemDescription.ToLower(), @"\w+")
        .Cast<Match>()
        .Select(m => m.Value)
    ).Any())
{
    ...
}

注: 文字列に次の単語が含まれているかどうかを確認するだけでは十分ではありません。

s.Contains("great")

「偉大さ」などの単語の一部も検出されるためです。


フレーズも検索する必要がある場合、上記のアプローチは機能しません。正規表現検索をループまたは LINQ ステートメントと組み合わせる必要があります。タイプの正規表現を使用しましょう

\bWordOrPhrase\b

\b単語境界に一致します。特殊な正規表現文字を正規表現に導入しないようにするために、単語またはフレーズをエスケープする必要があります。

bool found = Regex.IsMatch(description, @"\b" + Regex.Escape(wordOrPhrase) + @"\b");

最後に、リスト内のすべての単語とフレーズに対してこのテストを実行する必要があります。すべてをまとめましょう:

string dir = @"C:\MyDataPath";
string filename = comboTemplates.SelectedItem.ToString();
string filepath = Path.Combine(dir, filename);

string[] words = File.ReadAllLines(filepath);

次に、説明をテストします

string itemDescription = itemElement.GetElementsByTagName("description")[0].InnerText;
if (words.Any(
    wordOrPhrase =>
    Regex.IsMatch(itemDescription,
                  @"\b" + Regex.Escape(wordOrPhrase) + @"\b",
                  RegexOptions.IgnoreCase)))
{
    ...
}
于 2012-08-19T22:42:28.117 に答える