في مفهوم Vectors، قلنا إن "المصفوفات هي قلب لغة Julia" وإن المتجه أحادي البعد.
بناءً على ذلك، يمكننا أن نأمل بشكل معقول أن توفر اللغة أساليب كثيرة متعددة الاستخدامات وقوية للقيام بأشياء بالمتجهات، أيًا كان معنى ذلك.
هناك دوال بسيطة جدًا تأخذ متجهًا كمدخل وتُرجع قيمة قياسية.
v = [2, 3, 4]
length(v) # => 3
sum(v) # => 9
لنفترض أن لديك متجهًا عدديًا وتريد طرح 0.5 من كل قيمة.
julia> v = [1.2, 1.5, 1.7]
3-element Vector{Float64}:
1.2
1.5
1.7
julia> v - 0.5
ERROR: MethodError: no method matching -(::Vector{Float64}, ::Float64)
فشل ذلك، فما رأيك بطرح متجه آخر؟
julia> v - [0.5, 0.5, 0.5]
3-element Vector{Float64}:
0.7
1.0
1.2
نجح الأمر، لكنه مرهق جدًا ويستهلك الكثير من الذاكرة كلما طالت المتجهات.
لحسن الحظ، تمتلك Julia نقطة "سحرية" تحل هذه المشكلة ببساطة شديدة: كل ما تحتاجه هو v .- 0.5.
يشرح القسم التالي السبب.
إذن، يفشل v - 0.5 بينما ينجح v .- 0.5، ونحتاج إلى فهم ما تفعله النقطة.
أمران يتحدان ليعطيا النتيجة المرجوة.
أولًا، إضافة نقطة قبل أي عامل بيني تعني "طبّق هذه العملية على كل عنصر على حدة".
وبالمثل، إضافة نقطة بعد اسم دالة يجعلها تعمل على المتجهات كلها، حتى لو كانت الدالة مكتوبة أصلًا لمدخلات قياسية.
julia> sqrt.([1, 4, 9])
3-element Vector{Float64}:
1.0
2.0
3.0
رأينا في مثال سابق أنه يمكننا طرح متجهات متساوية الطول، لكن اعلم من فضلك أن .- عامل أكثر أمانًا من - لأنه يوضّح نية العمل عنصرًا عنصرًا.
julia> v .- [0.5, 0.5, 0.5]
3-element Vector{Float64}:
0.7
1.0
1.2
وماذا عن المتجهات غير المتساوية في الطول؟
julia> v .- [0.5, 0.5]
ERROR: DimensionMismatch: arrays could not be broadcast to a common size
julia> v .- [0.5,]
3-element Vector{Float64}:
0.7
1.0
1.2
بشكل عام، الأطوال غير المتساوية خطأ، إلا إذا كان طول أحدهما 1 (وهو ما يُسمى تقنيًا بُعدًا "مفردًا").
القيم المفردة مثل [0.5,] أو 0.5 بمفردها تُوسَّع تلقائيًا إلى الطول اللازم بالتكرار.
وهذا هو جوهر broadcasting.
سبق أن ناقشنا في مفاهيم سابقة اختيار عناصر متجه برقم الفهرس.
a = collect('A':'Z') # => 26-element Vector{Char}
# index with an integer
a[2] # => 'B'
# index with a range
a[12:2:18] # => ['L', 'N', 'P, 'R']
# index with another vector
a[ [1, 3, 5] ] # => ['A', 'C', 'E']
يمكن أيضًا اختيار العناصر التي تحقق تعبيرًا منطقيًا ما (وهو ما يُسمى تقنيًا "محمولًا"). وهذا يتطلب عادة استخدام البثّ.
julia> a[a .< 'D']
3-element Vector{Char}:
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)
في التعبيرات الأكثر تعقيدًا تميل النقاط إلى التكاثر (لكنها صغيرة ويسهل كتابتها).
julia> a[a .< 'D' .|| a .> 'W']
6-element Vector{Char}:
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)
'X': ASCII/Unicode U+0058 (category Lu: Letter, uppercase)
'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
'Z': ASCII/Unicode U+005A (category Lu: Letter, uppercase)
تذكير بأن "المتجه" يمكن أن يكون في الواقع أي كائن مناسب قابل للتكرار ومرتّب، مثل مدى:
julia> n = 3:10
3:10
julia> n[isodd.(n)]
4-element Vector{Int64}:
3
5
7
9
أنت مراقب طيور شغوف يتابع عدد الطيور التي زارت حديقتك خلال الأيام السبعة الماضية.
لديك ست مهام، وكلها تتعلق بأعداد الطيور التي زارت حديقتك.
نفّذ الدالة today() لتُرجع عدد الطيور التي زارت حديقتك اليوم.
أعداد الطيور مرتّبة حسب اليوم، بحيث يمثّل العنصر الأول عدد أقدم يوم، ويمثّل العنصر الأخير عدد اليوم.
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> today(birds_per_day)
1
نفّذ الدالة increment_todays_count() لزيادة عدد اليوم:
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> increment_todays_count(birds_per_day)
[2, 5, 0, 7, 4, 2]
نفّذ الدالة has_day_without_birds() التي تُرجع true إذا كان هناك يوم لم تزر فيه أي طيور الحديقة؛ وإلا، فأرجع false:
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> has_day_without_birds(birds_per_day)
true
نفّذ الدالة count_for_first_days() التي تُرجع عدد الطيور التي زارت حديقتك من بداية الأسبوع، لكن اقتصر العدد على عدد الأيام المحدد من بداية الأسبوع.
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> count_for_first_days(birds_per_day, 4)
14
بعض الأيام أكثر ازدحامًا من غيرها.
اليوم المزدحم هو اليوم الذي زارت فيه خمسة طيور أو أكثر حديقتك.
نفّذ الدالة busy_days() لتُرجع عدد الأيام المزدحمة:
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> busy_days(birds_per_day)
2
قررت توسيع سجلاتك بالاحتفاظ بأعداد لعدة أسابيع. في كل حالة، تُرتَّب الأعداد حسب أيام الأسبوع، من الاثنين كأول عنصر إلى الأحد كآخر عنصر.
نفّذ الدالة average_per_day() التي تُرجع المتوسط لأسبوعين.
julia> week1 = [7, 2, 9, 1, 3, 0, 10]
julia> week2 = [2, 6, 4, 1, 3, 8, 9]
julia> average_per_day(week1, week2)
[4.5, 4.0, 6.5, 1.0, 4.0, 3.0, 9.5]
سجّل في Exercism لتتعلّم وتتقن Julia عبر 35 مفهومًا128 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.