المصفوفة بنية بيانات قابلة للتغيير تخزّن مجموعة من العناصر من نوع محدّد. والمصفوفة بنية بيانات قابلة للفهرسة. وكون المصفوفات قابلة للتغيير يعني أنه إذا استُدعيت طريقة على المصفوفة تُعدّلها، فستُعدَّل المصفوفة نفسها. أي أنها لا تُنشئ مصفوفة جديدة، بل تُعدّل المصفوفة الموجودة.
لإنشاء مصفوفة، استخدم صيغة الكتابة الحرفية للمصفوفة ([])، وحدّد داخلها عناصر المصفوفة مفصولة بفاصلة.
[1, 2, 3] # => [1, 2, 3]
يستنتج Crystal نوع المصفوفة من العناصر.
[1, 2, 3].class # => Array(Int32)
رغم ما ذُكر سابقًا عن أن المصفوفة مجموعة عناصر من نوع محدّد، يمكنك إنشاء مصفوفة بأنواع متعددة باستخدام أنواع الاتحاد. يتيح ذلك للمصفوفة أن تحتوي على عناصر من أي الأنواع المحدّدة في نوع الاتحاد. ويستنتج Crystal نوع المصفوفة من العناصر.
[1, "2", 3.0] # => [1, "2", 3.0]
[1, "2", 3.0].class # => Array(Int32 | Float64 | String)
المصفوفة متعددة الأبعاد هي مصفوفة من المصفوفات.
أي أن كل عنصر في المصفوفة هو مصفوفة بحد ذاته.
وهذا مفيد عندما تريد تخزين البيانات في صورة جدول.
لتعريف مصفوفة متعددة الأبعاد، يمكنك إما كتابة مصفوفة من المصفوفات كتابة حرفية، أو استخدام الباني Array.new.
[[1, 2], [3, 4]] # => [[1, 2], [3, 4]]
numbers = Array(Array(Int32)).new() # => []
numbers << [1, 2] # => [[1, 2]]
لإضافة عنصر إلى مصفوفة، استخدم عامل << (الإلحاق).
[1, 2, 3] << 4 # => [1, 2, 3, 4]
يجب أن يكون نوع العنصر الذي تريد إضافته مطابقًا لنوع المصفوفة، وإلا فسيُرفع خطأ.
numbers : Array(Int32 | Float64) = [1, 2, 3]
numbers << 4.0
numbers # => [1, 2, 3, 4.0]
numbers << "5" # => Error: no overload matches 'Array(Int32 | Float64)#<<' with type String
وكما هو الحال مع String، يمكنك الحصول على حجم المصفوفة باستخدام طريقة size.
[1, 2, 3].size # => 3
لا يستطيع المصرِّف استنتاج نوع المصفوفة عند إنشاء مصفوفة فارغة.
لذلك عليك تحديد نوع المصفوفة.
ويمكن فعل ذلك بتحديد نوع المصفوفة باستخدام الكلمة المفتاحية of، أو باستخدام صيغة تهيئة المصفوفة، وهي Array(T).new.
[] of (Int32 | Float64 | String) # => []
Array(Int32 | Float64 | String).new # => []
وكما هو الحال مع String، يمكنك الوصول إلى عناصر المصفوفة باستخدام عامل الفهرسة [] وإعطائه فهرس العنصر الذي تريد الوصول إليه.
وإذا كان الفهرس خارج الحدود، فسيُرفع IndexError.
[1, 2, 3][0] # => 1
[1, 2, 3][3] # => Index out of bounds (IndexError)
ويمكن أيضًا الوصول إلى العناصر باستخدام مدى.
[1, 2, 3][0..1] # => [1, 2]
لإنشاء مصفوفة من مدى، استخدم طريقة to_a.
وهذا مفيد عندما تريد إنشاء مصفوفة من الأعداد.
(1..3).to_a # => [1, 2, 3]
لإنشاء مصفوفة من سلسلة نصية، استخدم طريقة split.
تتيح لك هذه الطريقة تقسيم سلسلة نصية إلى مصفوفة من السلاسل النصية باستخدام فاصل.
"1,2,3".split(",") # => ["1", "2", "3"]
ويمكن أيضًا الحصول على مصفوفة من المحارف من سلسلة نصية باستخدام طريقة chars.
"123".chars # => ['1', '2', '3']
لتحويل مصفوفة من Char أو String إلى String يمكنك استخدام طريقة join التي تأخذ فاصلًا كوسيط.
['1', '2', '3'].join(".") # => "1.2.3"
عندما تريد حذف عنصر من نهاية مصفوفة، يمكنك استخدام طريقة pop، التي تأخذ وسيطًا اختياريًا يحدّد عدد العناصر التي تريد إزالتها من نهاية المصفوفة.
وتُرجع الطريقة العنصر الذي حُذف.
وإذا كانت المصفوفة فارغة، فسيُرفع IndexError.
numbers = [1, 2, 3]
numbers.pop # => 3
numbers # => [1, 2]
empty_numbers = [] of Int32
empty_numbers.pop # => Index out of bounds (IndexError)
عندما تريد حذف عنصر عند فهرس محدّد من مصفوفة، يمكنك استخدام طريقة delete_at التي تأخذ فهرس العنصر المراد حذفه كوسيط.
وإذا كانت المصفوفة فارغة، فسيُرفع IndexError.
numbers = [1, 2, 3]
numbers.delete_at(1) # => 2
numbers # => [1, 3]
empty_numbers = [] of Int32
empty_numbers.delete_at(0) # => Index out of bounds (IndexError)
عندما تريد تعديل عنصر عند فهرس محدّد في مصفوفة، يمكنك استخدام عامل إسناد الفهرس []= الذي يأخذ فهرس العنصر المراد تعديله والقيمة الجديدة كوسيطين.
وإذا كان الفهرس خارج الحدود، فسيُرفع IndexError.
numbers = [1, 2, 3]
numbers[1] = 4
numbers # => [1, 4, 3]
numbers[3] = 5 # => Index out of bounds (IndexError)
في هذا التمرين، ستحتاج إلى تنفيذ بعض الطرق للتعامل مع مصفوفة من لغات البرمجة.
عرّف الطريقة LanguageList.list التي لا تأخذ أي وسائط وتُرجع مصفوفة فارغة من النوع Array(String).
LanguageList.list()
# => []
عرّف الطريقة LanguageList.add التي تأخذ وسيطين (مصفوفة لغات و سلسلة نصية حرفية تمثل لغة).
ينبغي أن تُرجع الطريقة المصفوفة بعد إضافة اللغة الجديدة إلى نهاية المصفوفة.
language_list = LanguageList.list()
# => []
language_list = LanguageList.add(language_list, "Crystal")
# => ["Crystal"]
language_list = LanguageList.add(language_list, "Ruby")
# => ["Crystal", "Ruby"]
عرّف الطريقة LanguageList.remove التي تأخذ وسيطًا واحدًا (مصفوفة لغات).
ينبغي أن تُرجع الطريقة المصفوفة دون العنصر الأخير.
افترض أن المصفوفة تحتوي دائما على عنصر واحد على الأقل.
language_list = LanguageList.list()
# => []
language_list = LanguageList.add(language_list, "Crystal")
# => ["Crystal"]
language_list = LanguageList.add(language_list, "Ruby")
# => ["Crystal", "Ruby"]
language_list = LanguageList.remove(language_list)
# => ["Crystal"]
عرّف الطريقة LanguageList.at التي تأخذ وسيطين (مصفوفة لغات و فهرس).
ينبغي أن تُرجع الطريقة اللغة الموجودة عند الفهرس n في المصفوفة.
افترض أن هناك دائما لغة عند هذا الفهرس.
language_list = LanguageList.new()
# => []
language_list = LanguageList.add(language_list, "Crystal")
# => ["Crystal"]
language_list = LanguageList.add(language_list, "Ruby")
# => ["Crystal", "Ruby"]
LanguageList.at(language_list, 1)
# => "Ruby"
عرّف الطريقة LanguageList.parse التي تأخذ وسيطًا واحدًا (سلسلة نصية حرفية من اللغات مفصولة بفاصلة).
ينبغي أن تُرجع الطريقة مصفوفة من اللغات.
LanguageList.parse("Crystal, Ruby")
# => ["Crystal", "Ruby"]
سجّل في Exercism لتتعلّم وتتقن Crystal عبر 26 مفهومًا142 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.