الفرز باستخدام Lambda
جزء من قسم Logic & Flow في رحلة C++ على Coddy — الدرس 47 من 56.
توفر مكتبة C++ القياسية دالة قوية تسمى std::sort من الترويسة <algorithm> التي يمكنها فرز الحاويات مثل المتجهات (vectors).
بشكل افتراضي، يقوم std::sort بترتيب العناصر بترتيب تصاعدي (من الأصغر إلى الأكبر). ومع ذلك، يمكنك تخصيص هذا السلوك من خلال توفير تعبير لامبدا (lambda expression) يحدد كيفية مقارنة العناصر:
#include <vector>
#include <algorithm>
std::vector<int> numbers = {5, 2, 8, 1, 9};
// الترتيب تنازلياً باستخدام لامبدا
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a > b; // إرجاع true إذا كان يجب أن يسبق a العنصر b
});تأخذ دالة lambda معاملين يمثلان العناصر التي تتم مقارنتها وتعيد true إذا كان العنصر الأول يجب أن يأتي قبل الثاني في النتيجة المرتبة. للترتيب التنازلي، نعيد true عندما a > b، مما يضع الأرقام الأكبر أولاً.
يوضح هذا كيف تجعل تعبيرات لامبدا (lambdas) من السهل تخصيص وظائف المكتبة القياسية دون الحاجة إلى كتابة وظائف مقارنة منفصلة، مما يبقي منطق الفرز الخاص بك في المكان الذي تحتاجه فيه تماماً.
التحدي
سهلقم بإنشاء برنامج يوضح الفرز المخصص باستخدام تعبيرات لامبدا (lambda expressions) مع std::sort. سيختبر هذا التحدي فهمك لكيفية استخدام دوال لامبدا لتحديد منطق مقارنة مخصص لفرز الحاويات (containers).
سيتم توفير المدخلات التالية:
- عدد صحيح
nيمثل عدد العناصر في المتجه (vector) nمن الأعداد الصحيحة التي تمثل العناصر المراد فرزها- حرف
orderيمثل ترتيب الفرز (Aللتصاعدي، وDللتنازلي)
يجب على برنامجك القيام بما يلي:
- إنشاء
std::vector<int>وتعبئته بالأرقام المدخلة - استخدام
std::sortمن ملف الترويسة<algorithm>مع تعبير لامبدا لفرز المتجه - يجب أن يأخذ تعبير لامبدا معاملين من نوع عدد صحيح ويعيد قيمة منطقية (boolean)
- بناءً على حرف الترتيب (order)، قم بتنفيذ منطق المقارنة المناسب داخل تعبير لامبدا
- طباعة كل عنصر من عناصر المتجه المفروز في سطر منفصل
يجب أن يكون سلوك الفرز كما يلي:
- إذا كان
orderهوA: يتم الفرز بترتيب تصاعدي (من الأصغر إلى الأكبر) - إذا كان
orderهوD: يتم الفرز بترتيب تنازلي (من الأكبر إلى الأصغر)
استخدم تنسيق المخرجات الدقيق التالي:
[first_sorted_element]
[second_sorted_element]
...
[last_sorted_element]تذكر أن std::sort يأخذ ثلاثة معاملات: مكرر البداية (beginning iterator)، ومكرر النهاية (ending iterator)، ودالة مقارنة. استخدم vector.begin() و vector.end() للمكررات. يجب أن تعيد دالة مقارنة لامبدا true إذا كان المعامل الأول يجب أن يأتي قبل المعامل الثاني في النتيجة المفروزة. للترتيب التصاعدي، أعد a < b؛ وللترتيب التنازلي، أعد a > b.
ورقة مرجعية
تقوم الدالة std::sort من الترويسة <algorithm> بفرز الحاويات مثل المتجهات (vectors). بشكل افتراضي، تقوم بالفرز بترتيب تصاعدي، ولكن يمكنك تخصيص سلوك الفرز باستخدام تعبير لامبدا (lambda expression).
الصيغة الأساسية:
std::sort(container.begin(), container.end(), comparison_lambda);يأخذ تعبير لامبدا معاملين يمثلان العناصر التي يتم مقارنتها، ويعيد true إذا كان يجب أن يأتي العنصر الأول قبل الثاني في النتيجة المفروزة.
مثال - الترتيب التنازلي:
#include <algorithm>
#include <vector>
std::vector<int> numbers = {5, 2, 8, 1, 9};
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a > b; // الأرقام الأكبر تأتي أولاً
});مثال - الترتيب التصاعدي:
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a < b; // الأرقام الأصغر تأتي أولاً
});جرّب بنفسك
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
// قراءة المدخلات
int n;
cin >> n;
vector<int> numbers(n);
for (int i = 0; i < n; i++) {
cin >> numbers[i];
}
char order;
cin >> order;
// TODO: اكتب كودك أدناه
// استخدم std::sort مع تعبير لامبدا (lambda expression) لفرز المتجه
// بناءً على حرف الترتيب (A للتصاعدي، D للتنازلي)
// طباعة العناصر المرتبة
for (int num : numbers) {
cout << num << endl;
}
return 0;
}يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Logic & Flow
1المؤشرات والذاكرة
ما هو المؤشر؟معامل العنوان (Address-Of)معامل الوصول للقيمة (Dereference)المؤشرات الفارغة (Null Pointers)المؤشرات والمصفوفاتالذاكرة الديناميكية باستخدام 'new'تحرير الذاكرة باستخدام 'delete'مراجعة - تمارين على المؤشرات4الخرائط (أزواج مفتاح-قيمة)
مقدمة إلى std::mapإنشاء خريطةالوصول إلى القيم وتعديلهاالتحقق من وجود المفاتيححذف الأزواجالتكرار عبر الخريطةمراجعة - تكرار الكلمات7الدوال المتقدمة
التمرير بالمرجعمقدمة في تعبيرات Lambdaتعبيرات Lambda مع المعاملاتتعبيرات Lambda مع قيم الإرجاعمقدمة في الاستدعاء الذاتيالمضروب بالاستدعاء الذاتيالفرز باستخدام Lambda2المتجهات (المصفوفات الديناميكية)
مقدمة إلى std::vectorإنشاء Vectorإضافة العناصرالوصول إلى العناصرحجم الـ Vectorالتكرار باستخدام For Loopالـ Range-Based For Loopإزالة العناصرملخص - عمليات الـ Vector