🧱 القوائم المتعددة الأبعاد (Multi-Dimensional List) في Dart
🔹 وتُعرف أيضًا بـ القوائم المتداخلة أو المصفوفات الثنائية.
✅ ما هي Multi-Dimensional List؟
هي قائمة تحتوي على قوائم بداخلها.
مثال:
List<List<int>> matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
JavaScript↪ هذا يمثل “مصفوفة” 3 صفوف × 3 أعمدة.
🧠 لماذا نستخدمها؟
- تمثيل الجداول.
- تمثيل بيانات الصفوف والأعمدة (مثل قواعد البيانات).
- إنشاء ألعاب شبكية (مثل Tic-Tac-Toe).
- بيانات الطلاب والدرجات، إلخ…
🔹 كيفية إنشاء قائمة ثنائية الأبعاد:
إما مباشرة:
List<List<String>> names = [
['Ali', 'Sara'],
['Omar', 'Lina'],
];
JavaScriptأو ديناميكيًا:
List<List<int>> grid = List.generate(3, (i) => List.generate(3, (j) => 0));
JavaScript⬅ ينشئ مصفوفة 3×3 مملوءة بالأصفار.
🟦 الوصول إلى عنصر داخل القائمة المتداخلة
print(matrix[0][1]); // النتيجة: 2
JavaScript↪ matrix[0]
تعني الصف الأول
↪ [1]
تعني العنصر الثاني من هذا الصف
🔁 التكرار على القوائم المتعددة الأبعاد
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
print('Element at [$i][$j] = ${matrix[i][j]}');
}
}
JavaScript🔄 باستخدام for-in
:
for (var row in matrix) {
for (var value in row) {
print(value);
}
}
JavaScript✍️ مثال تطبيقي
جدول درجات الطلاب
List<List<int>> grades = [
[90, 85, 88], // درجات الطالب 1
[70, 75, 72], // الطالب 2
[100, 98, 99], // الطالب 3
];
// طباعة متوسط درجات كل طالب
for (int i = 0; i < grades.length; i++) {
double avg = grades[i].reduce((a, b) => a + b) / grades[i].length;
print('Student ${i + 1} average: $avg');
}
JavaScript✳️ استبدال عنصر داخل القائمة المتعددة
matrix[2][1] = 100; // استبدال العنصر في الصف الثالث والعمود الثاني
JavaScript🟡 هل يمكن أن تكون ثلاثية أو أكثر؟
نعم، يمكن أن تكون قائمة من قائمة من قائمة:
List<List<List<int>>> cube = [
[
[1, 2],
[3, 4]
],
[
[5, 6],
[7, 8]
]
];
JavaScript✅ ملخص سريع
المفهوم | المثال |
---|---|
إنشاء قائمة 2D | List<List<int>> matrix = [...] |
الوصول لعنصر | matrix[row][col] |
تعديل عنصر | matrix[1][2] = 99 |
التكرار داخل 2D List | for داخل for |
إنشاء ديناميكي | List.generate(...) |
🔁 Spread Operator في Dart
وهو جزء مهم جدًا عند التعامل مع القوائم (Lists)، وخصوصًا عند دمج القوائم أو نسخ عناصرها.
✅ ما هو الـ Spread Operator؟
هو الرمز: ...
يُستخدم لنسخ جميع عناصر قائمة داخل قائمة أخرى.
🟢 مثال بسيط:
List<int> list1 = [1, 2, 3];
List<int> list2 = [4, 5, 6];
List<int> combined = [...list1, ...list2];
print(combined); // [1, 2, 3, 4, 5, 6]
JavaScript📌 بدون spread:
List<int> combined = [list1, list2]; // ❌ هذا ينشئ قائمة داخل قائمة
print(combined); // [[1, 2, 3], [4, 5, 6]]
******************************************
List<int> combined = [];
combined.addAll(list1);
combined.addAll(list2);
print(combined); // [1, 2, 3, 4, 5, 6]
JavaScript🟡 الشرطية مع spread (Null-Aware Spread)
إذا كانت القائمة قد تكون null
، نستخدم ...?
List<int>? optionalList = null;
List<int> result = [0, ...?optionalList, 100];
print(result); // [0, 100] بدون خطأ
//////////////////////////////////////////////
List<int> combined = [];
combined.addAll(list1);
combined.addAll(list2);
print(combined); // [1, 2, 3, 4, 5, 6]
JavaScriptلو استعملت
...optionalList
بدون?
، سيحدث خطأ إذا كانتnull
.
🧠 استخدام عملي: إنشاء قائمة جديدة من قائمة مع إضافة عناصر
List<String> base = ['PHP', 'Dart'];
List<String> withNew = [...base, 'JavaScript'];
print(withNew); // ['PHP', 'Dart', 'JavaScript']
JavaScript🛠️ استخدام مع الشروط (Collection if)
bool addJS = true;
List<String> langs = [
'PHP',
'Dart',
if (addJS) ...['JavaScript', 'TypeScript']
];
print(langs); // ['PHP', 'Dart', 'JavaScript', 'TypeScript']
JavaScript🔄 مقارنة النسخ اليدوي مقابل spread
✅ الطريقة اليدوية:
List<int> a = [1, 2, 3];
List<int> b = [];
for (var x in a) {
b.add(x);
}
JavaScript✅ مع spread:
List<int> b = [...a];
JavaScriptأسرع وأوضح!
✅ ملخص
الاستخدام | المثال |
---|---|
دمج قائمتين | [...] |
إضافة عناصر من قائمة إلى أخرى | newList = [...list1, 'item'] |
التعامل مع null | ...?list |
مع شرط | if (condition) ...[items] |
🔍 دالة where()
في Dart
✅ ما هي where()
؟
هي دالة تُستخدم مع القوائم (List) و المجموعات (Set) و الخرائط (Map) لتصفية العناصر حسب شرط معين.
ترجع where()
كائنًا من النوع Iterable
يحتوي على العناصر التي تنطبق عليها الشروط.
✅ الصيغة العامة:
list.where((element) => شرط)
JavaScript- ترجع قائمة جديدة تحتوي فقط على العناصر التي تحقق الشرط.
- لا تؤثر على القائمة الأصلية.
- يمكن تحويل الناتج إلى
List
باستخدام.toList()
إذا أردت استخدامه كقائمة عادية.
🧠 فوائد where()
:
الفائدة | الشرح |
---|---|
🔎 التصفية | استخراج عناصر مطابقة لشرط معين |
✅ تسهيل القراءة | أكثر وضوحًا من for مع if |
🔁 قابلة للسلسلة | يمكن دمجها مع map() أو reduce() |
📋 لا تعدل الأصل | تُعيد نسخة مصفاة دون تغيير القائمة الأصلية |
🟢 أين تُستخدم؟
- تصفية أرقام أو أسماء.
- البحث عن عناصر تحقق شروط.
- التعامل مع بيانات الطلاب، المنتجات، الخ…
- تقليص النتائج أو تحليل البيانات.
✳️ مثال 1: تصفية الأرقام الزوجية
List<int> numbers = [1, 2, 3, 4, 5, 6];
var evens = numbers.where((n) => n % 2 == 0).toList();
print(evens); // [2, 4, 6]
JavaScript✳️ مثال 2: تصفية أسماء تبدأ بحرف معيّن
List<String> names = ['Ali', 'Sara', 'Omar', 'Salma'];
var sNames = names.where((name) => name.startsWith('S')).toList();
print(sNames); // [Sara, Salma]
JavaScript✳️ مثال 3: تصفية درجات النجاح فقط
List<int> grades = [45, 75, 60, 30, 80];
var passed = grades.where((grade) => grade >= 50).toList();
print(passed); // [75, 60, 80]
JavaScript✳️ مثال 4: تصفية منتجات غالية الثمن
List<Map<String, dynamic>> products = [
{'name': 'Phone', 'price': 500},
{'name': 'Watch', 'price': 150},
{'name': 'Laptop', 'price': 1000},
];
var expensive = products.where((p) => p['price'] > 400).toList();
print(expensive);
// [{'name': 'Phone', 'price': 500}, {'name': 'Laptop', 'price': 1000}]
JavaScript⚠️ ملاحظة مهمة:
where()
تُعيدIterable
، وليسList
مباشرة.- استخدم
.toList()
لتحويل النتيجة إلىList
عند الحاجة.
✅ ملخص سريع
السؤال | الجواب |
---|---|
ماذا تفعل؟ | تُرجع عناصر مطابقة لشرط |
هل تغير القائمة الأصلية؟ | ❌ لا |
هل يجب تحويل الناتج إلى List؟ | يفضل: toList() |
هل يمكن استخدامها مع map أو reduce ؟ | ✅ نعم |
🔍 شرح مفصل لـ:
where()
firstWhere()
whereType<T>()
مع أمثلة لكل واحدة وتوضيح متى نستخدم كل واحدة منها.
🟢 1. where()
✅ ما تفعل:
ترجع جميع العناصر التي تحقق شرطًا معينًا.
✅ النوع الذي تُرجعه:
Iterable<T>
→ ويمكن تحويله إلى List
باستخدام .toList()
.
📌 مثال 1: تصفية الأعداد الزوجية
List<int> numbers = [1, 2, 3, 4, 5, 6];
var evens = numbers.where((n) => n % 2 == 0).toList();
print(evens); // [2, 4, 6]
JavaScript📌 مثال 2: تصفية أسماء تبدأ بحرف “A”
List<String> names = ['Ali', 'Omar', 'Ahmed', 'Sara'];
var aNames = names.where((name) => name.startsWith('A')).toList();
print(aNames); // [Ali, Ahmed]
JavaScript✅ متى نستخدم where()
؟
عندما نريد كل العناصر التي تحقق شرطًا معينًا.
🟢 2. firstWhere()
✅ ما تفعل:
ترجع أول عنصر فقط يحقق شرطًا معينًا.
لو لم يوجد، يمكن إرجاع قيمة افتراضية.
✅ النوع الذي تُرجعه:
T
→ قيمة مفردة من نفس نوع العناصر.
📌 مثال 1: أول رقم أكبر من 10
List<int> numbers = [3, 7, 15, 20];
int first = numbers.firstWhere((n) => n > 10);
print(first); // 15
JavaScript📌 مثال 2: استخدام قيمة افتراضية إذا لم يوجد شيء
List<String> names = ['Sara', 'Lina'];
String result = names.firstWhere(
(name) => name.startsWith('Z'),
orElse: () => 'Not Found',
);
print(result); // Not Found
JavaScript✅ متى نستخدم firstWhere()
؟
عندما نريد عنصرًا واحدًا فقط يطابق الشرط (غالبًا أول عنصر).
🟢 3. whereType<T>()
✅ ما تفعل:
تُرجع العناصر التي تنتمي لنوع معيّن فقط من القائمة.
✅ مفيدة عند التعامل مع قائمة تحتوي أنواع مختلفة.
📌 مثال: استخراج الأعداد فقط من قائمة مختلطة
List<dynamic> mixed = [1, 'hello', true, 2.5, 42];
var onlyInts = mixed.whereType<int>().toList();
print(onlyInts); // [1, 42]
JavaScript📌 مثال: استخراج السلاسل النصية فقط
List<dynamic> mixed = ['Hi', 100, 'World', false];
var strings = mixed.whereType<String>().toList();
print(strings); // ['Hi', 'World']
JavaScript✅ متى نستخدم whereType<T>()
؟
عندما تكون قائمتك تحتوي على أنواع بيانات متعددة وتريد استخراج نوع محدد فقط (مثل فقط النصوص، أو الأرقام).
🟡 ملخص المقارنة:
الدالة | ما تُرجعه | تُستخدم عندما… |
---|---|---|
where() | Iterable<T> | تريد كل العناصر التي تحقق شرطًا |
firstWhere() | T (عنصر واحد) | تريد أول عنصر فقط يحقق شرطًا |
whereType<T>() | Iterable<T> | تريد تصفية حسب النوع فقط |