الـ Maps المتداخلة
جزء من قسم Logic & Flow في رحلة Dart على Coddy — الدرس 31 من 65.
أحياناً تحتاج إلى تنظيم البيانات في هيكل هرمي أكثر تعقيداً من مجرد زوج بسيط من المفتاح والقيمة. تسمح لك الخرائط المتداخلة (Nested maps) بتخزين خرائط كقيم داخل خرائط أخرى، مما يؤدي إلى إنشاء مستويات متعددة من تنظيم البيانات.
الخريطة المتداخلة (nested map) هي ببساطة Map حيث تكون القيم بحد ذاتها كائنات Map. هذا الهيكل مثالي لتمثيل البيانات التي تحتوي على فئات وفئات فرعية، مثل ملفات تعريف المستخدمين ذات التفاصيل المتعددة، أو كتالوجات المنتجات ذات السمات المتنوعة.
Map<String, Map<String, dynamic>> userProfiles = {
'alice': {
'email': 'alice@example.com',
'age': 28
},
'bob': {
'email': 'bob@example.com',
'age': 32
}
};
print(userProfiles['alice']['email']); // alice@example.com
print(userProfiles['bob']['age']); // 32للوصول إلى البيانات في خريطة متداخلة (nested map)، يمكنك استخدام مجموعات متعددة من الأقواس المربعة. تصل المجموعة الأولى إلى مفتاح الخريطة الخارجية، وتصل المجموعة الثانية إلى مفتاح الخريطة الداخلية. يسهل هذا الهيكل المكون من مستويين تجميع المعلومات ذات الصلة معاً مع الحفاظ على تنظيمها وإمكانية الوصول إليها.
التحدي
سهلقم بإنشاء برنامج يدير نظام دليل موظفي الشركة باستخدام الخرائط المتداخلة (nested maps) لتخزين معلومات الموظفين التفصيلية. يجب على برنامجك القيام بما يلي:
- قراءة مدخل نصي (string) يمثل اسم الشركة.
- قراءة مجموعات متعددة من المدخلات التي تمثل بيانات الموظفين (سينتهي الإدخال عندما تتلقى
"employees_done"). سيحتوي كل موظف على:- معرف الموظف (string)
- الاسم (string)
- القسم (string)
- الراتب (string يحتاج إلى تحويله إلى عدد صحيح integer)
- سنوات الخبرة (string يحتاج إلى تحويله إلى عدد صحيح integer)
- قراءة مدخل نصي يمثل معرف الموظف المراد البحث عنه.
- إنشاء خريطة (Map) متداخلة حيث يكون كل معرف موظف هو المفتاح (key)، والقيمة (value) هي خريطة أخرى تحتوي على تفاصيل الموظف.
- الوصول إلى معلومات موظف محدد وعرضها باستخدام الوصول إلى الخرائط المتداخلة.
- حساب إحصائيات الأقسام وطباعة تقرير دليل الموظفين بالتنسيق الدقيق الموضح أدناه.
على سبيل المثال، إذا كان اسم الشركة هو "TechCorp Solutions"، وتضمنت بيانات الموظفين "EMP001" بالاسم "Alice Johnson"، والقسم "Engineering"، والراتب 75000، والخبرة 5، و "EMP002" بالاسم "Bob Smith"، والقسم "Marketing"، والراتب 60000، والخبرة 3، و "EMP003" بالاسم "Carol Davis"، والقسم "Engineering"، والراتب 80000، والخبرة 7، وكان معرف الموظف المراد البحث عنه هو "EMP001"، فيجب أن تكون مخرجات برنامجك:
Company: TechCorp Solutions
Employee Directory: {EMP001: {name: Alice Johnson, department: Engineering, salary: 75000, experience: 5}, EMP002: {name: Bob Smith, department: Marketing, salary: 60000, experience: 3}, EMP003: {name: Carol Davis, department: Engineering, salary: 80000, experience: 7}}
Employee Lookup (EMP001):
Name: Alice Johnson
Department: Engineering
Salary: $75000
Experience: 5 years
Department Analysis:
Engineering employees: 2
Marketing employees: 1
Total employees: 3
Average salary: $71666
Status: Employee directory processed successfullyإذا كان اسم الشركة هو "Global Industries"، وتضمنت بيانات الموظفين "E100" بالاسم "David Wilson"، والقسم "Sales"، والراتب 55000، والخبرة 4، و "E101" بالاسم "Emma Brown"، والقسم "HR"، والراتب 65000، والخبرة 6، وكان معرف الموظف المراد البحث عنه هو "E101"، فيجب أن تكون مخرجات برنامجك:
Company: Global Industries
Employee Directory: {E100: {name: David Wilson, department: Sales, salary: 55000, experience: 4}, E101: {name: Emma Brown, department: HR, salary: 65000, experience: 6}}
Employee Lookup (E101):
Name: Emma Brown
Department: HR
Salary: $65000
Experience: 6 years
Department Analysis:
Sales employees: 1
HR employees: 1
Total employees: 2
Average salary: $60000
Status: Employee directory processed successfullyإذا كان اسم الشركة هو "StartupHub"، وتضمنت بيانات الموظفين "S001" بالاسم "Frank Miller"، والقسم "Development"، والراتب 70000، والخبرة 2، و "S002" بالاسم "Grace Lee"، والقسم "Design"، والراتب 58000، والخبرة 3، و "S003" بالاسم "Henry Chen"، والقسم "Development"، والراتب 72000، والخبرة 4، و "S004" بالاسم "Ivy Taylor"، والقسم "Marketing"، والراتب 62000، والخبرة 5، وكان معرف الموظف المراد البحث عنه هو "S003"، فيجب أن تكون مخرجات برنامجك:
Company: StartupHub
Employee Directory: {S001: {name: Frank Miller, department: Development, salary: 70000, experience: 2}, S002: {name: Grace Lee, department: Design, salary: 58000, experience: 3}, S003: {name: Henry Chen, department: Development, salary: 72000, experience: 4}, S004: {name: Ivy Taylor, department: Marketing, salary: 62000, experience: 5}}
Employee Lookup (S003):
Name: Henry Chen
Department: Development
Salary: $72000
Experience: 4 years
Department Analysis:
Development employees: 2
Design employees: 1
Marketing employees: 1
Total employees: 4
Average salary: $65500
Status: Employee directory processed successfullyيجب أن ينشئ برنامجك هيكل Map متداخل حيث تستخدم الخريطة الخارجية معرفات الموظفين كمفاتيح، وتكون كل قيمة عبارة عن خريطة داخلية تحتوي على "name" و "department" و "salary" و "experience" كمفاتيح. استخدم الوصول إلى الخريطة المتداخلة باستخدام الأقواس المربعة المزدوجة لاسترداد معلومات موظف محدد. قم بعد الموظفين حسب القسم واحسب متوسط الراتب عن طريق قسمة مجموع الرواتب الإجمالي على عدد الموظفين. سيكون تنسيق الإدخال هو: اسم الشركة، ثم مجموعات من خمس قيم (معرف الموظف، الاسم، القسم، الراتب، الخبرة) تنتهي بـ "employees_done"، متبوعة بمعرف الموظف المراد البحث عنه.
ورقة مرجعية
تسمح لك الخرائط المتداخلة (Nested maps) بتخزين خرائط كقيم داخل خرائط أخرى، مما يؤدي إلى إنشاء هياكل بيانات هرمية:
Map<String, Map<String, dynamic>> userProfiles = {
'alice': {
'email': 'alice@example.com',
'age': 28
},
'bob': {
'email': 'bob@example.com',
'age': 32
}
};يمكنك الوصول إلى بيانات الخرائط المتداخلة باستخدام أقواس مربعة متعددة:
print(userProfiles['alice']['email']); // alice@example.com
print(userProfiles['bob']['age']); // 32يصل القوس الأول إلى مفتاح الخريطة الخارجية، بينما يصل القوس الثاني إلى مفتاح الخريطة الداخلية.
جرّب بنفسك
import 'dart:io';
void main() {
// قراءة اسم الشركة
String? companyName = stdin.readLineSync();
// تهيئة خريطة متداخلة لدليل الموظفين
Map<String, Map<String, dynamic>> employeeDirectory = {};
// قراءة بيانات الموظفين حتى "employees_done"
while (true) {
String? input = stdin.readLineSync();
if (input == "employees_done") {
break;
}
String employeeId = input!;
String? name = stdin.readLineSync();
String? department = stdin.readLineSync();
String? salaryStr = stdin.readLineSync();
String? experienceStr = stdin.readLineSync();
// تحويل الراتب والخبرة إلى أعداد صحيحة
int salary = int.parse(salaryStr!);
int experience = int.parse(experienceStr!);
// TODO: إنشاء هيكل خريطة متداخل لكل موظف وإضافته إلى الدليل
}
// قراءة معرف الموظف للبحث عنه
String? lookupId = stdin.readLineSync();
// TODO: اكتب الكود الخاص بك أدناه من أجل:
// 1. عرض اسم الشركة ودليل الموظفين
// 2. البحث عن معلومات موظف معين وعرضها
// 3. حساب إحصائيات القسم
// 4. حساب متوسط الراتب
// 5. طباعة التقرير الكامل بالتنسيق المطلوب
}يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Logic & Flow
1التعامل المتقدم مع القوائم
خصائص القائمة: first و lastحالة القائمة: isEmpty و isNotEmptyعكس القائمةالإضافة إلى القائمة: insertالحذف من القائمة: removeWhereالبحث في القائمة: indexOfفرز القائمةخلط القائمةملخص - منظم القوائم4معالجة الـ Map المتقدمة
التكرار عبر الـ Mapالتحقق من المفاتيح والقيمخصائص الـ Map: keys و valuesإضافة مشروطة: putIfAbsentإزالة العناصر من الـ Mapالـ Maps المتداخلةمراجعة - تحديث المخزون2عمليات القوائم الوظيفية
التحويل باستخدام 'map'التصفية باستخدام 'where'استخدام '.toList()'التحقق من الشروط باستخدام 'any'الشروط باستخدام 'every'البحث باستخدام 'firstWhere'مراجعة - تصفية البيانات5مشروع: حاسبة عربة التسوق
إعداد المشروعإضافة العناصر إلى العربة3المجموعات
ما هي المجموعة؟إنشاء مجموعةالإضافة والحذف من المجموعاتالتحقق من وجود عناصر في المجموعةتحويل قائمة إلى مجموعةاتحاد المجموعاتتقاطع المجموعاتالفرق بين المجموعاتمراجعة - قائمة ضيوف فريدة