رأينا في الدرس السابق(http://www.vbnetworld.com/content/view/236/26/) كيف يمكننا تعداد تكرارا كلمة معينة في نص ما وذلك بواسطة تقنية ال LINQ الجديدة في .NET FrameWork 3.5 و التي مكنتنا بعمل ما نريد بطريقة بسيطة و سلسة، اليوم سوف نحاول التعامل مع ال Strings مرة أخرى بواسطة ال LINQ لكن هذه المرة المهمة ستكون بالبحث في نص معين عن جمل تحتوي على جمل معينة كيف ذلك ؟ سوف نرى كل شئ في التفاصيل.
التفاصيل :
كما هوواضح من خلال عنوان الدرس اليوم فهو سيكون عمل كود يقوم بالبحث في نص معين و يرجع لنا الجمل التي تحتوي على كلمات معينة ، و حتى تتوضح الفكرة دعونا نسرد مثالا بسيطا :
ليكن لدينا النص التالي :
LEFT TO RIGHT
I love arabteam2000 because i have many friends here. And also i love visual basic !!!
في النص التالي كما هو واضح لدينا جملتين ومانريد فعله هوالحث او ارجاع الجملة التي تحتوي على الكلمات التالية :
LEFT TO RIGHT
love visual
و هنا لا يهمنا مكان الكلمات المهم ان تكون الكلمات في الجملة. طبعا هذا الأمر يفيد كثيرا مثلا عندما نريد عمل برنامج يبحث في ملفات نصية على جمل معينة داخلها. الكود الذي سنكتبه سيمكننا من ارجاع الجملة الثانية كنتيجة
LEFT TO RIGHT
And also i love visual basic
اذن دعونا من الكلام و لنتوجه مباشرة لمتطلبات برنامجنا او كودنا البسيط.
متطلبات البرنامج :
أنشأ مشروع جديد من نوع Console Application
اختر نوع ال FrameWork 3.5
عمل Imports System.Linq
الكود :
سوف نقوم بكتابة النص الذي سنجري عليه البحث ك Hard-Coded و طبعا يمكنك أن تقوم بأخذ النص من أي مكان تريد :
كود
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."[/font]
Dim GetSentences() As String = Text.Split(New String() {".", "!", "?"}, StringSplitOptions.RemoveEmptyEntries)
Dim SearchedWords() As String = {"Historically", "data", "integrated"}
Dim SearchQuery = From Sentence In GetSentences _
Let words = Sentence.Split(New String() {".", "?", "!", " ", ";", ":", ","}, StringSplitOptions.RemoveEmptyEntries) _
Where words.Distinct().Intersect(SearchedWords).Count = SearchedWords.Count _
Select Sentence
For Each ReturnedSentence In SearchQuery
Console.WriteLine(ReturnedSentence)
Next
Console.ReadKey()
End Sub
شرح الكود :
أولا قمنا بانشاء String تحتوي على نص ما وهوالنص التي سيتم البحث فيه، بعد ذلك قمنا بانشاء متغير GetSentences() و استخدمنا الفنكشن Split و التي بها قمنا بتجزيئ النص الى جمل و كما تلاحظ في استخدام ال Split لم نستخدم فقط Separator واحد بل مجموعة منهم :
كود
Dim GetSentences() As String = Text.Split(New String() {".", "!", "?"}, StringSplitOptions.RemoveEmptyEntries)
و ال Separators هنا هي التي تعني انتهاء جملة معينة طبعا لم ندخل الفاصلة لأنها لا تحد الجملة و هكذا نكون قد حصلنا على Array تحتوي على جميع الجمل الموجودة في النص.
بعد ذلك قمنا بتحديد الكلمات التي نريد البحث عنها في الجمل :
كود
Dim SearchedWords() As String = {"Historically", "data", "integrated"}
أنا هنا جعلت هذه التعابير Hard-Coded لكن يمكنك ان تجعلها ديناميكية في برنامجك.
الآن و بعد أن أخذنا الجمل و حددنا التعابير الذي سنبحث عنها يبقى لنا كتابة ال Query التي ستقوم بالحدث وتعيد لنا النتائج:
كود
Dim SearchQuery = From Sentence In GetSentences _
Let words = Sentence.Split(New String() {".", "?", "!", " ", ";", ":", ","}, StringSplitOptions.RemoveEmptyEntries) _
Where words.Distinct().Intersect(SearchedWords).Count = SearchedWords.Count _
Select Sentence
أعرف انه للوهلة الأولى تظهر هذه ال Query معقدة لكن بعد أن اقوم بشرحها تأكد أنها لن تبقى بنفس التعقيد، كما هو معتاد قمنا ببداية ال Query بكتابة الجملة From و نتبعها بمتغير ثم نتبعها بال Collection التي سنبحث فيها ما يبدوجديدا الآن هو تعبير Let هذا التعبير يمكننا من اعلان متغير و اعطاءه قيمة داخل ال Query نفسها !!!! أليس هذا رائعا
اذن دعونا نرى هذا التعبير على حدى :
كود
Let words = Sentence.Split(New String() {".", "?", "!", " ", ";", ":", ","}, StringSplitOptions.RemoveEmptyEntries)
بكل بساطة هذا السطر يقوم باعلان متغير words والذي سوف يحتوي على الكلمات من الجمل التي لدينا يعني يقسم الجمل الى كلمات و يضعها في المتغير words تماما كما راينا مع تقسيم النص الى جمل و طبعا هنا Sentence ستحتوي على الجمل (لا حظ ان تنفيذ ال Query لا يتم في هذه المرحلة بل فقط عند عمل Iteration هذه نقطة مهمة قد أكتب شيئا عنها لاحقا) بعد ذلك نكتب الشرط الخاص بارجاع النتيجة و الشرط كما ذكرنا اولا هو ان تكون الجملة التي نبحث عنها تحتوي على التعابير التي حددناها في المتغير SearchedWords و الشرط يكتب كالتالي :
كود
Where words.Distinct().Intersect(SearchedWords).Count = SearchedWords.Count _
Select Sentence
مممممم !!! قطعة كود جميلة ولذيذة، لكنها غير مفهومة لي ، ممكن تشرحها ؟؟؟
طبعا سأشرحها لك فجماليتها لن تكتمل الا بشرحها
ال Where Clause يقوم كما قلنا بتحديد شرط و هنا الشرط ان تحتوي الجملة على التعابير المحددة بعد Where نجد هذا الكود :
بكل بساطة ال Distinct() تقوم بحذف أي تكرار من المتغير words وكما تعلم المتغير words عبارة عن Array تحتوي على الكلمات المكونة لجملة محددة فمثلا لنأخذ الجملة التالية :
LEFT TO RIGHT
I love visual basic language , basic is my favorite language
المهم هذه الجملة عند تقسيمها الى كلمات ووضعها في Array ستكون كالتالي :
LEFT TO RIGHT
I love visual basic language basic is my favorite language
الآن لوقمنا بتنفيذ ال Method التي ذكرنا وهي Distinct النتيجة ستكون كالتالي :
LEFT TO RIGHT
I [size=3]love visual basic language is my favorite
لاحظ معي أنه قام بحذف التكرار. الآن نمر الى ال Intersect وهذه الMethod تقوم بارجاع ال Elements المكررة في مصفوفتين مثلا يعني لوأخذنا مصفوفتين من نوع Integer
كود
id1() As Integer = {44, 26, 92, 30, 71, 38}
Dim id2() As Integer = {39, 59, 83, 47, 26, 4, 30}
Dim intersection As IEnumerable(Of Integer) = id1.Intersect(id2)
الآن المتغير intersection سيحتوي على العناصر الموجودة في ال id1 و ال id2 و هي : 26 30
اذا لو أطللنا مرة أخرى على الكود سوف يكون مفهوما :
فكل مانعمل هوحذف التكرار من مصفوفة الكلمات ثم نبحث في المصفوفة عن العناصر المشابهة للعناصر التي حددناها في المصفوفة SearchedWords و نفحص عدد العناصر المشابهة اذا كانت تساوي عدد العناصر الموجودة في ال SearchedWords يكون الشرط قد تحقق و نقوم بارجاع الجملة
كود
Select Sentence
نتيجة الاستعلام ستكون الجملة :
LEFT TO RIGHT
Historically, the world of data and the world of objects have not been well integrated
خاتمة :
أتمنى أن يكون هذا الدرس البسيط قد أضاف اليك بعضا من الجديد في الفيجوال 2008 و يكون حافزا ايضا لأن تجرب الفيجوال 2008 و طبعا كما قلت في بداية الدرس يمكنك استعمال هذا الكود في أن تقوم بعمل برنامج يقوم بالبحث في الملفات النصية عن تعابير معينة و أمور مثل هذه و أتركك لتجربة الأمر و الاستمتاع