Skip to content

📊 مشروع: محلل ملفات CSV

متقدم⏱️ 60 دقيقة📁 ملف واحد

ما الذي سنبنيه؟

أداة قوية لتحليل ملفات CSV:

📊 محلل CSV
═══════════════════════════════

الملف: موظفين.csv
الأعمدة: الاسم، القسم، الراتب، سنوات_الخبرة

═══ الإحصائيات ═══
عدد السجلات: 150
عدد الأعمدة: 4

═══ عمود "الراتب" ═══
المجموع: 1,250,000
المتوسط: 8,333
الأعلى: 25,000
الأدنى: 3,000

═══ تصفية ═══
الموظفون براتب > 10000: 35 سجل

ما ستتعلمه

  • ✅ قراءة ومعالجة الملفات النصية الكبيرة
  • ✅ تقسيم وتحليل النصوص
  • ✅ استخدام الأصناف لتنظيم البيانات
  • ✅ حساب الإحصائيات (مجموع، متوسط، أعلى/أدنى)
  • ✅ تصفية البيانات بشروط

الخطوة 1: هيكل البيانات

نبدأ بتعريف الأصناف:

sad
# ═══════════════════════════════════════
# محلل CSV — هياكل البيانات
# ═══════════════════════════════════════

# صنف يمثل صفاً واحداً من البيانات
صنف صف
    باني(قيم)
        هذا.قيم = قيم  # مصفوفة القيم
    نهاية
    
    دالة احصل(فهرس)
        إذا (فهرس < طول(هذا.قيم))
            ارجع هذا.قيم[فهرس]
        نهاية
        ارجع ""
    نهاية
نهاية

# صنف يمثل جدول CSV كامل
صنف جدول_CSV
    باني()
        هذا.عناوين = []    # أسماء الأعمدة
        هذا.صفوف = []      # مصفوفة من كائنات صف
    نهاية
    
    دالة عدد_الصفوف()
        ارجع طول(هذا.صفوف)
    نهاية
    
    دالة عدد_الأعمدة()
        ارجع طول(هذا.عناوين)
    نهاية
نهاية

الخطوة 2: قراءة ملف CSV

sad
من أساسيات استورد اقرأ_ملف، ملف_موجود

# === قراءة وتحليل ملف CSV ===
دالة اقرأ_CSV(مسار_الملف)
    # التحقق من وجود الملف
    إذا (ليس ملف_موجود(مسار_الملف))
        ارمي "الملف غير موجود: " + مسار_الملف
    نهاية
    
    # قراءة المحتوى
    متغير محتوى = اقرأ_ملف(مسار_الملف)
    متغير أسطر = محتوى.تقسيم("\n")
    
    # إنشاء الجدول
    متغير جدول = جدول_CSV()
    
    لكل ي في 0..طول(أسطر)
        متغير سطر = أسطر[ي].قص_أطراف()
        
        # تخطي الأسطر الفارغة
        إذا (طول(سطر) == 0)
            استمر
        نهاية
        
        # تقسيم بالفاصلة
        متغير قيم = سطر.تقسيم("،")
        
        # إذا لم تنجح الفاصلة العربية، جرّب اللاتينية
        إذا (طول(قيم) == 1)
            قيم = سطر.تقسيم(",")
        نهاية
        
        # تنظيف القيم
        لكل ج في 0..طول(قيم)
            قيم[ج] = قيم[ج].قص_أطراف()
        نهاية
        
        # السطر الأول = العناوين
        إذا (ي == 0)
            جدول.عناوين = قيم
        وإلا
            جدول.صفوف.أضف(صف(قيم))
        نهاية
    نهاية
    
    ارجع جدول
نهاية

الخطوة 3: الوصول للبيانات

نُضيف دوال للوصول السهل للبيانات:

sad
# === الحصول على فهرس عمود بالاسم ===
دالة فهرس_العمود(جدول، اسم_العمود)
    لكل ي في 0..طول(جدول.عناوين)
        إذا (جدول.عناوين[ي] == اسم_العمود)
            ارجع ي
        نهاية
    نهاية
    ارجع -1  # غير موجود
نهاية

# === استخراج قيم عمود كامل ===
دالة قيم_العمود(جدول، اسم_العمود)
    متغير فهرس = فهرس_العمود(جدول، اسم_العمود)
    
    إذا (فهرس == -1)
        ارمي "العمود غير موجود: " + اسم_العمود
    نهاية
    
    متغير قيم = []
    لكل صف في جدول.صفوف
        قيم.أضف(صف.احصل(فهرس))
    نهاية
    
    ارجع قيم
نهاية

# === استخراج قيم عمود كأرقام ===
دالة قيم_العمود_رقمية(جدول، اسم_العمود)
    متغير نصوص = قيم_العمود(جدول، اسم_العمود)
    متغير أرقام = []
    
    لكل ن في نصوص
        حاول
            أرقام.أضف(عشري(ن))
        امسك خ
            # تخطي القيم غير الرقمية
        نهاية
    نهاية
    
    ارجع أرقام
نهاية

الخطوة 4: الإحصائيات

sad
# === صنف الإحصائيات ===
صنف إحصائيات
    باني(قيم)
        هذا.قيم = قيم
        هذا.العدد = طول(قيم)
    نهاية
    
    دالة المجموع()
        متغير مج = 0
        لكل ق في هذا.قيم
            مج = مج + ق
        نهاية
        ارجع مج
    نهاية
    
    دالة المتوسط()
        إذا (هذا.العدد == 0)
            ارجع 0
        نهاية
        ارجع هذا.المجموع() / هذا.العدد
    نهاية
    
    دالة الأعلى()
        إذا (هذا.العدد == 0)
            ارجع 0
        نهاية
        
        متغير أعلى = هذا.قيم[0]
        لكل ق في هذا.قيم
            إذا (ق > أعلى)
                أعلى = ق
            نهاية
        نهاية
        ارجع أعلى
    نهاية
    
    دالة الأدنى()
        إذا (هذا.العدد == 0)
            ارجع 0
        نهاية
        
        متغير أدنى = هذا.قيم[0]
        لكل ق في هذا.قيم
            إذا (ق < أدنى)
                أدنى = ق
            نهاية
        نهاية
        ارجع أدنى
    نهاية
    
    دالة اعرض()
        اطبع_سطر(م"  العدد: {هذا.العدد}")
        اطبع_سطر(م"  المجموع: {هذا.المجموع()}")
        اطبع_سطر(م"  المتوسط: {هذا.المتوسط()}")
        اطبع_سطر(م"  الأعلى: {هذا.الأعلى()}")
        اطبع_سطر(م"  الأدنى: {هذا.الأدنى()}")
    نهاية
نهاية

# === حساب إحصائيات عمود ===
دالة إحصائيات_العمود(جدول، اسم_العمود)
    متغير قيم = قيم_العمود_رقمية(جدول، اسم_العمود)
    ارجع إحصائيات(قيم)
نهاية

الخطوة 5: التصفية

sad
# === تصفية الصفوف بشرط ===
دالة رشّح(جدول، اسم_العمود، شرط)
    متغير فهرس = فهرس_العمود(جدول، اسم_العمود)
    
    إذا (فهرس == -1)
        ارمي "العمود غير موجود: " + اسم_العمود
    نهاية
    
    متغير نتائج = []
    
    لكل صف في جدول.صفوف
        متغير قيمة = صف.احصل(فهرس)
        
        # تطبيق دالة الشرط
        إذا (شرط(قيمة))
            نتائج.أضف(صف)
        نهاية
    نهاية
    
    # إنشاء جدول جديد بالنتائج
    متغير جدول_جديد = جدول_CSV()
    جدول_جديد.عناوين = جدول.عناوين
    جدول_جديد.صفوف = نتائج
    
    ارجع جدول_جديد
نهاية

# === أمثلة على دوال الشرط ===
دالة أكبر_من_10000(قيمة)
    حاول
        ارجع عشري(قيمة) > 10000
    امسك خ
        ارجع خطأ
    نهاية
نهاية

دالة يحتوي_أحمد(قيمة)
    ارجع قيمة.يحتوي("أحمد")
نهاية

الخطوة 6: التصدير

sad
من أساسيات استورد اكتب_ملف

# === تصدير جدول إلى CSV ===
دالة صدّر_CSV(جدول، مسار_الملف)
    متغير محتوى = ""
    
    # كتابة العناوين
    محتوى = محتوى + جدول.عناوين.ضم("،") + "\n"
    
    # كتابة الصفوف
    لكل صف في جدول.صفوف
        محتوى = محتوى + صف.قيم.ضم("،") + "\n"
    نهاية
    
    اكتب_ملف(مسار_الملف، محتوى)
    اطبع_سطر("💾 تم التصدير إلى: " + مسار_الملف)
نهاية

# === عرض الجدول بشكل مُنسّق ===
دالة اعرض_الجدول(جدول، حد)
    # عرض العناوين
    اطبع_سطر("┌" + "─".تكرار(60) + "┐")
    اطبع("│ ")
    لكل ع في جدول.عناوين
        اطبع(ع + " │ ")
    نهاية
    اطبع_سطر("")
    اطبع_سطر("├" + "─".تكرار(60) + "┤")
    
    # عرض الصفوف (محدود)
    متغير عدد = 0
    لكل صف في جدول.صفوف
        إذا (عدد >= حد)
            توقف
        نهاية
        
        اطبع("│ ")
        لكل ق في صف.قيم
            اطبع(ق + " │ ")
        نهاية
        اطبع_سطر("")
        عدد = عدد + 1
    نهاية
    
    اطبع_سطر("└" + "─".تكرار(60) + "┘")
    
    إذا (جدول.عدد_الصفوف() > حد)
        اطبع_سطر(م"... و {جدول.عدد_الصفوف() - حد} صف إضافي")
    نهاية
نهاية

الكود الكامل

📄 انقر لعرض الكود الكامل
sad
# ═══════════════════════════════════════════════════════════════
# مشروع: محلل ملفات CSV
# الوصف: أداة لقراءة وتحليل وتصفية ملفات CSV
# ═══════════════════════════════════════════════════════════════

من أساسيات استورد اقرأ_ملف، اكتب_ملف، ملف_موجود

# ═══════════════════════════════════════
# هياكل البيانات
# ═══════════════════════════════════════

صنف صف
    باني(قيم)
        هذا.قيم = قيم
    نهاية
    
    دالة احصل(فهرس)
        إذا (فهرس < طول(هذا.قيم))
            ارجع هذا.قيم[فهرس]
        نهاية
        ارجع ""
    نهاية
نهاية

صنف جدول_CSV
    باني()
        هذا.عناوين = []
        هذا.صفوف = []
    نهاية
    
    دالة عدد_الصفوف()
        ارجع طول(هذا.صفوف)
    نهاية
    
    دالة عدد_الأعمدة()
        ارجع طول(هذا.عناوين)
    نهاية
نهاية

صنف إحصائيات
    باني(قيم)
        هذا.قيم = قيم
        هذا.العدد = طول(قيم)
    نهاية
    
    دالة المجموع()
        متغير مج = 0
        لكل ق في هذا.قيم
            مج = مج + ق
        نهاية
        ارجع مج
    نهاية
    
    دالة المتوسط()
        إذا (هذا.العدد == 0)
            ارجع 0
        نهاية
        ارجع هذا.المجموع() / هذا.العدد
    نهاية
    
    دالة الأعلى()
        إذا (هذا.العدد == 0)
            ارجع 0
        نهاية
        متغير أعلى = هذا.قيم[0]
        لكل ق في هذا.قيم
            إذا (ق > أعلى)
                أعلى = ق
            نهاية
        نهاية
        ارجع أعلى
    نهاية
    
    دالة الأدنى()
        إذا (هذا.العدد == 0)
            ارجع 0
        نهاية
        متغير أدنى = هذا.قيم[0]
        لكل ق في هذا.قيم
            إذا (ق < أدنى)
                أدنى = ق
            نهاية
        نهاية
        ارجع أدنى
    نهاية
    
    دالة اعرض(اسم)
        اطبع_سطر(م"═══ إحصائيات «{اسم}» ═══")
        اطبع_سطر(م"  العدد: {هذا.العدد}")
        اطبع_سطر(م"  المجموع: {هذا.المجموع()}")
        اطبع_سطر(م"  المتوسط: {هذا.المتوسط()}")
        اطبع_سطر(م"  الأعلى: {هذا.الأعلى()}")
        اطبع_سطر(م"  الأدنى: {هذا.الأدنى()}")
    نهاية
نهاية

# ═══════════════════════════════════════
# دوال القراءة
# ═══════════════════════════════════════

دالة اقرأ_CSV(مسار)
    إذا (ليس ملف_موجود(مسار))
        ارمي "الملف غير موجود: " + مسار
    نهاية
    
    متغير محتوى = اقرأ_ملف(مسار)
    متغير أسطر = محتوى.تقسيم("\n")
    متغير جدول = جدول_CSV()
    
    لكل ي في 0..طول(أسطر)
        متغير سطر = أسطر[ي].قص_أطراف()
        
        إذا (طول(سطر) == 0)
            استمر
        نهاية
        
        متغير قيم = سطر.تقسيم("،")
        إذا (طول(قيم) == 1)
            قيم = سطر.تقسيم(",")
        نهاية
        
        لكل ج في 0..طول(قيم)
            قيم[ج] = قيم[ج].قص_أطراف()
        نهاية
        
        إذا (ي == 0)
            جدول.عناوين = قيم
        وإلا
            جدول.صفوف.أضف(صف(قيم))
        نهاية
    نهاية
    
    ارجع جدول
نهاية

# ═══════════════════════════════════════
# دوال الوصول
# ═══════════════════════════════════════

دالة فهرس_العمود(جدول، اسم)
    لكل ي في 0..طول(جدول.عناوين)
        إذا (جدول.عناوين[ي] == اسم)
            ارجع ي
        نهاية
    نهاية
    ارجع -1
نهاية

دالة قيم_العمود(جدول، اسم)
    متغير فهرس = فهرس_العمود(جدول، اسم)
    إذا (فهرس == -1)
        ارمي "العمود غير موجود: " + اسم
    نهاية
    
    متغير قيم = []
    لكل صف في جدول.صفوف
        قيم.أضف(صف.احصل(فهرس))
    نهاية
    ارجع قيم
نهاية

دالة قيم_رقمية(جدول، اسم)
    متغير نصوص = قيم_العمود(جدول، اسم)
    متغير أرقام = []
    
    لكل ن في نصوص
        حاول
            أرقام.أضف(عشري(ن))
        امسك خ
            # تخطي
        نهاية
    نهاية
    
    ارجع أرقام
نهاية

دالة إحصائيات_العمود(جدول، اسم)
    ارجع إحصائيات(قيم_رقمية(جدول، اسم))
نهاية

# ═══════════════════════════════════════
# دوال التصفية
# ═══════════════════════════════════════

دالة رشّح(جدول، اسم_العمود، شرط)
    متغير فهرس = فهرس_العمود(جدول، اسم_العمود)
    إذا (فهرس == -1)
        ارمي "العمود غير موجود"
    نهاية
    
    متغير نتائج = []
    لكل صف في جدول.صفوف
        إذا (شرط(صف.احصل(فهرس)))
            نتائج.أضف(صف)
        نهاية
    نهاية
    
    متغير جديد = جدول_CSV()
    جديد.عناوين = جدول.عناوين
    جديد.صفوف = نتائج
    ارجع جديد
نهاية

# ═══════════════════════════════════════
# دوال العرض والتصدير
# ═══════════════════════════════════════

دالة اعرض_معلومات(جدول)
    اطبع_سطر("")
    اطبع_سطر("═══ معلومات الجدول ═══")
    اطبع_سطر(م"  عدد الصفوف: {جدول.عدد_الصفوف()}")
    اطبع_سطر(م"  عدد الأعمدة: {جدول.عدد_الأعمدة()}")
    اطبع("  الأعمدة: ")
    لكل ع في جدول.عناوين
        اطبع(ع + " | ")
    نهاية
    اطبع_سطر("")
نهاية

دالة اعرض_الجدول(جدول، حد)
    اطبع_سطر("")
    
    لكل ع في جدول.عناوين
        اطبع(ع + "\t")
    نهاية
    اطبع_سطر("")
    اطبع_سطر("─".تكرار(50))
    
    متغير عدد = 0
    لكل صف في جدول.صفوف
        إذا (عدد >= حد)
            توقف
        نهاية
        لكل ق في صف.قيم
            اطبع(ق + "\t")
        نهاية
        اطبع_سطر("")
        عدد = عدد + 1
    نهاية
    
    إذا (جدول.عدد_الصفوف() > حد)
        اطبع_سطر(م"... و {جدول.عدد_الصفوف() - حد} صف إضافي")
    نهاية
نهاية

دالة صدّر_CSV(جدول، مسار)
    متغير محتوى = جدول.عناوين.ضم("،") + "\n"
    
    لكل صف في جدول.صفوف
        محتوى = محتوى + صف.قيم.ضم("،") + "\n"
    نهاية
    
    اكتب_ملف(مسار، محتوى)
    اطبع_سطر("💾 تم التصدير إلى: " + مسار)
نهاية

# ═══════════════════════════════════════
# البرنامج الرئيسي — مثال استخدام
# ═══════════════════════════════════════

دالة رئيسية()
    اطبع_سطر("╔══════════════════════════════╗")
    اطبع_سطر("║     📊 محلل ملفات CSV       ║")
    اطبع_سطر("╚══════════════════════════════╝")
    
    # إنشاء ملف CSV للاختبار
    متغير بيانات_اختبار = """الاسم،القسم،الراتب،سنوات_الخبرة
أحمد محمد،تقنية،12000،5
سارة علي،مبيعات،8500،3
محمد خالد،تقنية،15000،8
فاطمة أحمد،موارد بشرية،9000،4
عمر سعيد،تقنية،18000،10
نورة محمد،مبيعات،7500،2
خالد عبدالله،مالية،11000،6
ريم فهد،تقنية،14000،7
"""
    
    اكتب_ملف("موظفين.csv"، بيانات_اختبار)
    اطبع_سطر("✅ تم إنشاء ملف اختبار: موظفين.csv")
    
    # قراءة الملف
    حاول
        متغير جدول = اقرأ_CSV("موظفين.csv")
        
        # عرض المعلومات
        اعرض_معلومات(جدول)
        
        # عرض البيانات
        اطبع_سطر("")
        اطبع_سطر("═══ البيانات (أول 5 صفوف) ═══")
        اعرض_الجدول(جدول، 5)
        
        # إحصائيات الراتب
        اطبع_سطر("")
        متغير إحصاء = إحصائيات_العمود(جدول، "الراتب")
        إحصاء.اعرض("الراتب")
        
        # تصفية — رواتب أعلى من 10000
        اطبع_سطر("")
        اطبع_سطر("═══ تصفية: راتب > 10000 ═══")
        متغير مرشّح = رشّح(جدول، "الراتب"، لامدا(ق) => عشري(ق) > 10000)
        اطبع_سطر(م"عدد النتائج: {مرشّح.عدد_الصفوف()}")
        اعرض_الجدول(مرشّح، 10)
        
        # تصدير النتائج
        صدّر_CSV(مرشّح، "رواتب_عالية.csv")
        
    امسك خطأ
        اطبع_سطر("❌ خطأ: " + خطأ)
    نهاية
نهاية

رئيسية()

📁 ملف CSV للاختبار

أنشئ ملف موظفين.csv:

csv
الاسم،القسم،الراتب،سنوات_الخبرة
أحمد محمد،تقنية،12000،5
سارة علي،مبيعات،8500،3
محمد خالد،تقنية،15000،8
فاطمة أحمد،موارد بشرية،9000،4
عمر سعيد،تقنية،18000،10
نورة محمد،مبيعات،7500،2
خالد عبدالله،مالية،11000،6
ريم فهد،تقنية،14000،7

🏆 تحديات إضافية

  1. ترتيب البيانات — رتّب الصفوف حسب عمود معين
  2. تجميع البيانات — احسب مجموع الرواتب لكل قسم
  3. رسم بياني نصي — اعرض توزيع الرواتب كـ bar chart
  4. دمج ملفات — ادمج ملفين CSV في واحد
  5. التحقق من البيانات — اكتشف القيم الفارغة أو غير الصحيحة

ماذا تعلمت؟

  • ✅ قراءة ومعالجة الملفات النصية
  • ✅ تصميم أصناف لتمثيل البيانات
  • ✅ تقسيم النصوص وتحليلها
  • ✅ استخدام اللامدا للتصفية المرنة
  • ✅ حساب الإحصائيات الأساسية
  • ✅ تصدير البيانات بتنسيق محدد

🎉 أكملت جميع المشاريع!

تهانينا! لقد بنيت ثلاثة تطبيقات حقيقية بلغة ص:

  1. ✅ قائمة مهام CLI — إدارة البيانات والملفات
  2. ✅ لعبة تخمين الرقم — المنطق وحلقات اللعب
  3. ✅ محلل CSV — معالجة البيانات والإحصائيات

الخطوة التالية:

مُرخَّص بموجب رخصة MIT