Gewusst wie: Abfragen von Sätzen, die eine angegebene Gruppe von Wörtern (LINQ) enthalten

Aktualisiert: November 2007

In diesem Beispiel wird veranschaulicht, wie Sätze in einer Textdatei gesucht werden, die Übereinstimmungen für jede Gruppe einer angegebenen Gruppe von Wörtern enthalten. Das Array von Suchbegriffen ist in diesem Beispiel zwar fest programmiert, es könnte aber auch dynamisch zur Laufzeit gefüllt werden. In diesem Beispiel gibt die Abfrage die Sätze zurück, die die Wörter "Historically", "data" und "integrated" enthalten.

Beispiel

Class FindSentences

    Shared Sub Main()
        Dim text As String = "Historically, the world of data and the world of objects " & _
        "have not been well integrated. Programmers work in C# or Visual Basic " & _
        "and also in SQL or XQuery. On the one side are concepts such as classes, " & _
        "objects, fields, inheritance, and .NET Framework APIs. On the other side " & _
        "are tables, columns, rows, nodes, and separate languages for dealing with " & _
        "them. Data types often require translation between the two worlds; there are " & _
        "different standard functions. Because the object world has no notion of query, a " & _
        "query can only be represented as a string without compile-time type checking or " & _
        "IntelliSense support in the IDE. Transferring data from SQL tables or XML trees to " & _
        "objects in memory is often tedious and error-prone."

        ' Split the text block into an array of sentences.
        Dim sentences As String() = text.Split(New Char() {".", "?", "!"})

        ' Define the search terms. This list could also be dynamically populated at runtime
        Dim wordsToMatch As String() = {"Historically", "data", "integrated"}

        ' Find sentences that contain all the terms in the wordsToMatch array
        ' Note that the number of terms to match is not specified at compile time
        Dim sentenceQuery = From sentence In sentences _
                            Let w = sentence.Split(New Char() {" ", ",", ".", ";", ":"}, _
                                                   StringSplitOptions.RemoveEmptyEntries) _
                            Where w.Distinct().Intersect(wordsToMatch).Count = wordsToMatch.Count() _
                            Select sentence

        ' Execute the query
        For Each str As String In sentenceQuery
            Console.WriteLine(str)
        Next

        ' Keep console window open in debug mode.
        Console.WriteLine("Press any key to exit.")
        Console.ReadKey()
    End Sub

End Class
' Output:
' Historically, the world of data and the world of objects have not been well integrated
class FindSentences
{
    static void Main()
    {
        string text = @"Historically, the world of data and the world of objects " +
        @"have not been well integrated. Programmers work in C# or Visual Basic " +
        @"and also in SQL or XQuery. On the one side are concepts such as classes, " +
        @"objects, fields, inheritance, and .NET Framework APIs. On the other side " +
        @"are tables, columns, rows, nodes, and separate languages for dealing with " +
        @"them. Data types often require translation between the two worlds; there are " +
        @"different standard functions. Because the object world has no notion of query, a " +
        @"query can only be represented as a string without compile-time type checking or " +
        @"IntelliSense support in the IDE. Transferring data from SQL tables or XML trees to " +
        @"objects in memory is often tedious and error-prone.";

        // Split the text block into an array of sentences.
        string[] sentences = text.Split(new char[] { '.', '?', '!' });

        // Define the search terms. This list could also be dynamically populated at runtime.
        string[] wordsToMatch = { "Historically", "data", "integrated" };

        // Find sentences that contain all the terms in the wordsToMatch array.
        // Note that the number of terms to match is not specified at compile time.
        var sentenceQuery = from sentence in sentences
                            let w = sentence.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' },
                                                    StringSplitOptions.RemoveEmptyEntries)
                            where w.Distinct().Intersect(wordsToMatch).Count() == wordsToMatch.Count()
                            select sentence;

        // Execute the query. Note that you can explicitly type
        // the iteration variable here even though sentenceQuery
        // was implicitly typed. 
        foreach (string str in sentenceQuery)
        {
            Console.WriteLine(str);
        }

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }
}
/* Output:
Historically, the world of data and the world of objects have not been well integrated
*/

Die Abfrage unterteilt dabei den Text zuerst in Sätze. Anschließend werden die Sätze in ein Array von Zeichenfolgen unterteilt, die die einzelnen Wörter enthalten. Für jedes dieser Arrays entfernt die Distinct-Methode alle doppelten Wörter, und dann führt die Abfrage eine Intersect-Operation für das Wortarray und das wordstoMatch-Array aus. Wenn die Anzahl in der Schnittmenge die gleiche ist, wie die Anzahl im wordsToMatch-Array, werden alle gefundenen Wörter und der ursprüngliche Satz zurückgegeben.

Im Aufruf von Split werden die Satzzeichen als Trennzeichen verwendet, um sie aus der Zeichenfolge zu entfernen. Wenn Sie nicht so vorgehen, könnten Sie z. B. eine Zeichenfolge "Historically," haben, die nicht mit "Historically" im wordsToMatch-Array übereinstimmt. Abhängig von den Satzzeichen im Ausgangstext müssen Sie möglicherweise zusätzliche Trennzeichen verwenden.

Kompilieren des Codes

  • Erstellen Sie ein Visual Studio-Projekt, das die .NET Framework Version 3.5 als Ziel hat. Standardmäßig weist das Projekt einen Verweis auf System.Core.dll und eine using-Direktive (C#) oder eine Imports-Anweisung (Visual Basic) für den System.Linq-Namespace auf. Fügen Sie in C#-Projekten eine using-Direktive für den System.IO-Namespace hinzu.

  • Kopieren Sie diesen Code ins Projekt.

  • Drücken Sie F5, um das Programm zu kompilieren und auszuführen.

  • Drücken Sie eine beliebige Taste, um das Konsolenfenster zu schließen.

Siehe auch

Konzepte

LINQ und Zeichenfolgen