تخطَّ إلى المحتوى

القوائم والخرائط في Dart: List و Map و Set

الدرس 6 من 14 · Dart

قائمة الرسائل في تطبيق المحادثة، ومنتجات المتجر، وإعدادات المستخدم: كلها مجموعات من البيانات. وفي Flutter، أغلب الشاشات التي ستبنيها تعرض قائمة من شيء ما. في هذا الدرس ستتعلم أهم ثلاثة أنواع للمجموعات في Dart: List و Map و Set.

مجموعة مرتبة من العناصر، كل عنصر له رقم (Index) يبدأ من صفر:

var colors = ['أحمر', 'أخضر', 'أزرق'];
print(colors[0]);
print(colors.length);
print(colors.last);
الناتج
أحمر
3
أزرق

تخيّلها مثل قطار: عربات متتالية مرقمة، وكل عربة فيها راكب.

ويمكنك تحديد نوع العناصر: List<int> scores = [85, 92];. والقائمة هنا لا تقبل إلا أرقاماً صحيحة.

colors.add('أصفر'); // أضف في النهاية
colors.remove('أخضر'); // احذف عنصراً بقيمته
colors[0] = 'بنفسجي'; // عدّل العنصر الأول
print(colors);
print(colors.contains('أزرق'));
print(colors.indexOf('أصفر'));
الناتج
[بنفسجي, أزرق, أصفر]
true
2

دوال أخرى مفيدة: insert(0, x) للإضافة في مكان محدد، و removeAt(i) للحذف بالرقم، و isEmpty و isNotEmpty لفحص الفراغ، و clear() لتفريغ القائمة.

هذه الدوال الثلاث ستستخدمها في كل تطبيق تقريباً:

List<int> scores = [85, 92, 78, 64];
var passed = scores.where((s) => s >= 75).toList();
print(passed);
var bonus = scores.map((s) => s + 5).toList();
print(bonus);
print(scores.reduce((a, b) => a + b));
scores.sort();
print(scores);
الناتج
[85, 92, 78]
[90, 97, 83, 69]
319
[64, 78, 85, 92]
  • where: تصفية. احتفظ فقط بالعناصر التي تحقق الشرط، مثل مصفاة القهوة.
  • map: تحويل. طبّق عملية على كل عنصر واحصل على قائمة جديدة.
  • reduce: اختزال. اجمع كل العناصر في قيمة واحدة.
  • sort(): ترتيب تصاعدي، ويعدّل القائمة نفسها.

لاحظ .toList() بعد where و map: هاتان الدالتان تُرجعان نوعاً اسمه Iterable، و toList() تحوله لقائمة عادية.

var more = [...colors, 'أسود'];
print(more);
var isAdmin = true;
var menu = ['الرئيسية', 'الكورسات', if (isAdmin) 'لوحة التحكم'];
print(menu);
الناتج
[بنفسجي, أزرق, أصفر, أسود]
[الرئيسية, الكورسات, لوحة التحكم]
  • ... (Spread): «افرد» عناصر قائمة داخل قائمة أخرى.
  • if داخل القائمة: أضف العنصر فقط إذا تحقق الشرط. في Flutter تستخدمها لإظهار زر أو إخفائه حسب حالة المستخدم.

مجموعة من أزواج مفتاح ← قيمة، مثل القاموس: تبحث بالكلمة (المفتاح) فتجد معناها (القيمة):

var student = {
'name': 'سارة',
'city': 'الإسكندرية',
};
print(student['name']);
student['grade'] = 'الثاني الإعدادي';
print(student.length);
print(student['phone']);
الناتج
سارة
3
null

لاحظ: طلب مفتاح غير موجود مثل 'phone' يُرجع null ولا ينهار البرنامج. لهذا نوع القيمة المقروءة من الخريطة يقبل null دائماً، وتحتاج ?? أو فحصاً قبل استخدامها، كما تعلمت في درس Null Safety.

Map<String, int> prices = {'قلم': 5, 'كراسة': 15, 'مسطرة': 7};
print(prices.keys);
print(prices.values);
print(prices.containsKey('قلم'));
prices.forEach((item, price) {
print('$item: $price جنيه');
});
الناتج
(قلم, كراسة, مسطرة)
(5, 15, 7)
true
قلم: 5 جنيه
كراسة: 15 جنيه
مسطرة: 7 جنيه

Map<String, int> تعني: المفاتيح نصوص، والقيم أرقام صحيحة. وللمرور بحلقة for استخدم entries:

var total = 0;
for (var entry in prices.entries) {
total += entry.value;
}
print('الإجمالي: $total');
الناتج
الإجمالي: 27

مثل القائمة، لكن بلا تكرار، وبلا ترتيب بأرقام:

var tags = {'dart', 'flutter', 'dart'};
print(tags);
print(tags.length);
الناتج
{dart, flutter}
2

dart المكررة حُذفت تلقائياً. استخدمها عندما يهمك «هل العنصر موجود؟» وليس «كم مرة؟».

البيانات الحقيقية: قائمة من الخرائط

Section titled “البيانات الحقيقية: قائمة من الخرائط”

البيانات القادمة من الإنترنت (JSON) تأتي غالباً بهذا الشكل:

var students = [
{'name': 'أحمد', 'score': 85},
{'name': 'منى', 'score': 92},
];
for (var s in students) {
print('${s['name']}: ${s['score']}');
}
الناتج
أحمد: 85
منى: 92

وفي الدرس القادم ستتعلم طريقة أفضل وأأمن لتمثيل كل طالب: الكلاسات.

احسب عدد مرات تكرار كل كلمة في قائمة، باستخدام خريطة:

void main() {
var words = ['تفاح', 'موز', 'تفاح', 'عنب', 'موز', 'تفاح'];
var counts = <String, int>{};
for (var w in words) {
counts[w] = (counts[w] ?? 0) + 1;
}
print(counts);
}
الناتج المتوقع
{تفاح: 3, موز: 2, عنب: 1}

لاحظ counts[w] ?? 0: في أول مرة تظهر الكلمة، قيمتها null، فنبدأ من صفر.

  • رقم خارج حدود القائمة: colors[10] في قائمة من 3 عناصر تسبب خطأ RangeError. تذكّر أن آخر رقم هو length - 1.
  • نسيان toList(): نتيجة map و where ليست List، فلن تجد فيها دوال مثل add.
  • استخدام قيمة الخريطة مباشرة: student['name'].length يرفضها المحرر لأن القيمة قد تكون null. استخدم ?. أو ??.

سؤال

ما ناتج [1, 2, 3, 4].where((n) => n > 2).toList()؟

سؤال

أي نوع مجموعة يحذف العناصر المكررة تلقائياً؟

  • List مرتبة بأرقام تبدأ من صفر، و add و remove و contains لتعديلها وفحصها.
  • where للتصفية، و map للتحويل، و reduce للاختزال، ومعها toList().
  • ... و if داخل القائمة لبنائها بمرونة.
  • Map أزواج مفتاح وقيمة، وقراءة مفتاح غير موجود تُرجع null.
  • Set بلا تكرار، والبيانات الحقيقية غالباً قائمة من الخرائط.