Практическое руководство. Запрос к предложениям, содержащим указанный набор слов (LINQ)
Обновлен: Ноябрь 2007
В этом примере показан поиск предложений, содержащих совпадения для каждого из указанного набора слов в текстовом файле. Хотя массив терминов для поиска в этом примере жестко закодирован, его можно заполнять динамически во время выполнения. В этом примере запрос возвращает предложения, которые содержат слова "Historically", "data" и "integrated."
Пример
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
*/
Запрос сначала разделяет текст на предложения, а затем разделяет предложения на массив строк, содержащих слова. Для каждого из этих массивов метод Distinct удаляет все повторяющиеся слова, а затем запрос выполняет операцию Intersect в массиве слов и массиве wordstoMatch. Если число пересечений совпадает с размером массива wordsToMatch, то все слова были найдены и возвращается исходное предложение.
В вызове Split знаки пунктуации используются как разделители для того, чтобы удалить их из строки. Если этого не сделать, то, например, можно получить строку "Historically," которая не будет совпадать с "Historically" в массиве wordsToMatch. В зависимости от знаков препинания в исходном тексте может потребоваться использовать дополнительные разделители.
Компиляция кода
Создайте проект Visual Studio, предназначенный для .NET Framework версии 3.5. По умолчанию в этом проекте имеется ссылка на файл System.Core.dll и директива using (C#) или оператор Imports (Visual Basic) для пространства имен System.Linq. При работе с проектами C# добавьте директиву using для пространства имен System.IO.
Скопируйте этот код в проект.
Нажмите клавишу F5, чтобы скомпилировать и выполнить программу.
Нажмите любую клавишу для выхода из окна консоли.