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

المصفوفات والقوائم في Kotlin: Array و List و Map

الدرس 6 من 11 · Kotlin

قائمة جهات الاتصال، والأغاني في تطبيق الموسيقى، ودرجات الطلاب: كلها مجموعات من البيانات. في Kotlin هناك عدة أنواع للمجموعات، ولكل نوع استخدامه. في هذا الدرس ستتعرف على المصفوفات، ثم على القوائم التي ستستخدمها أكثر بكثير، ثم على الخرائط.

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

val numbers = arrayOf(10, 20, 30)
println(numbers[0])
println(numbers.size)
numbers[1] = 25
println(numbers.joinToString())
الناتج
10
3
10, 25, 30
  • arrayOf(...): تنشئ المصفوفة.
  • numbers[0]: أول عنصر، و size عدد العناصر.
  • يمكن تعديل قيمة عنصر، لكن لا يمكن إضافة عناصر جديدة أو حذفها، فالحجم ثابت.

تخيّل المصفوفة مثل صندوق بيض: فيه أماكن محددة العدد، تستطيع تبديل بيضة بأخرى، لكن لا تستطيع إضافة مكان جديد.

في الواقع، ستستخدم القوائم أكثر من المصفوفات بكثير. و Kotlin تفرّق بين نوعين:

القائمة الثابتة List: للقراءة فقط، لا تُضاف إليها عناصر ولا تُحذف:

val colors = listOf("أحمر", "أخضر", "أزرق")
println(colors)
println(colors.first())
println(colors.last())
println(colors.contains("أزرق"))
الناتج
[أحمر, أخضر, أزرق]
أحمر
أزرق
true

القائمة القابلة للتعديل MutableList:

val tasks = mutableListOf("مذاكرة", "رياضة")
tasks.add("قراءة")
tasks.remove("رياضة")
tasks[0] = "مذاكرة Kotlin"
println(tasks)
println(tasks.size)
الناتج
[مذاكرة Kotlin, قراءة]
2

لاحظ أن tasks معرّفة بـ val، ومع ذلك أضفنا إليها وحذفنا منها! لأن val تعني أن المتغير لا يشير إلى قائمة أخرى، لكن محتوى القائمة القابلة للتعديل نفسه يمكن أن يتغير.

لماذا نوعان؟ القائمة الثابتة تحميك من التعديل بالخطأ. إذا مررت قائمة لدالة، وكانت List، فأنت متأكد أن الدالة لن تغيّرها. القاعدة: ابدأ بـ listOf، واستخدم mutableListOf فقط عندما تحتاج التعديل.

val scores = listOf(85, 92, 78, 64)
println(scores.filter { it >= 75 })
println(scores.map { it + 5 })
println(scores.sum())
println(scores.average())
println(scores.max())
println(scores.sorted())
println(scores.sortedDescending())
الناتج
[85, 92, 78]
[90, 97, 83, 69]
319
79.75
92
[64, 78, 85, 92]
[92, 85, 78, 64]
  • filter: يحتفظ بالعناصر التي تحقق الشرط.
  • map: يحوّل كل عنصر إلى قيمة جديدة.
  • sum و average و max: المجموع والمتوسط وأكبر قيمة.
  • sorted و sortedDescending: ترتيب تصاعدي وتنازلي، وتُرجعان قائمة جديدة دون تغيير الأصلية.

بهذه الدوال تكتب في سطر واحد ما يحتاج حلقة كاملة في لغات أخرى.

مجموعة أزواج مفتاح ← قيمة، مثل القاموس:

val prices = mapOf("قلم" to 5, "كراسة" to 15, "مسطرة" to 7)
println(prices["قلم"])
println(prices["ممحاة"])
for ((item, price) in prices) {
println("$item: $price جنيه")
}
println(prices.values.sum())
الناتج
5
null
قلم: 5 جنيه
كراسة: 15 جنيه
مسطرة: 7 جنيه
27
  • "قلم" to 5: تربط المفتاح بقيمته.
  • طلب مفتاح غير موجود مثل "ممحاة" يُرجع null، فنوع القيمة المقروءة يقبل null.
  • for ((item, price) in prices) تفكك كل زوج إلى مفتاح وقيمة.

وللخريطة نسخة قابلة للتعديل أيضاً:

val stock = mutableMapOf("تفاح" to 10)
stock["موز"] = 5
stock["تفاح"] = 8
println(stock)
الناتج
{تفاح=8, موز=5}

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

fun main() {
val words = listOf("تفاح", "موز", "تفاح", "عنب", "موز", "تفاح")
val counts = mutableMapOf<String, Int>()
for (w in words) {
counts[w] = (counts[w] ?: 0) + 1
}
println(counts)
}
الناتج المتوقع
{تفاح=3, موز=2, عنب=1}

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

تحدٍّ: من قائمة درجات، اطبع عدد الناجحين (75 فأكثر) ومتوسط درجاتهم فقط.

  • رقم خارج حدود القائمة: colors[5] في قائمة من 3 عناصر تسبب خطأ ArrayIndexOutOfBoundsException. آخر رقم هو size - 1.
  • محاولة add على List: listOf لا تقبل الإضافة. استخدم mutableListOf.
  • طباعة المصفوفة مباشرة: تطبع عنوانها في الذاكرة. استخدم joinToString().

سؤال

أي دالة تنشئ قائمة يمكن الإضافة إليها والحذف منها؟

سؤال

ما ناتج listOf(3, 8, 5).filter { it > 4 }؟

  • arrayOf مصفوفة بحجم ثابت، واطبعها بـ joinToString().
  • listOf قائمة للقراءة فقط، و mutableListOf قابلة للتعديل، وابدأ دائماً بالثابتة.
  • filter و map و sum و average و sorted تختصر الحلقات الطويلة.
  • mapOf("مفتاح" to قيمة) للخرائط، وقراءة مفتاح غير موجود تُرجع null.
  • الترقيم يبدأ من صفر، وآخر عنصر رقمه size - 1.