في Elm، Dict هو قاموس غير قابل للتغيير يتكوّن من صفر أو أكثر من أزواج المفتاح والقيمة.
تُعالَج القواميس بواسطة دوال وعوامل معرّفة في وحدة Dict.
تُكتب تعليقات النوع الخاصة بالقواميس على النحو التالي:
Dict String (List Int) --> a dict with String keys and List Int values
Dict Int String --> a dict with Int keys and String values
يمكن إنشاء القواميس كما يلي:
empty : Dict Int String
empty = Dict.empty
singleValue = Dict.singleton 5 "Value for key 5" --> Dict Int String
twoValues = Dict.fromList [ ( "Alice", 0 ), ( "Bob", 1 ) ] --> Dict String Int
يمكن استرجاع العناصر باستخدام get.
وبما أن المفتاح قد يكون موجودًا في القاموس أو لا، فستكون النتيجة مُغلَّفة داخل Maybe.
alice = Dict.fromList [ ( 0, "Alice" ) ]
keyExists = Dict.get 0 alice --> Just "Alice"
keyNotPresent = Dict.get 1 alice --> Nothing
يمكن إضافة العناصر باستخدام insert.
أما العناصر ذات المفاتيح الموجودة بالفعل في القاموس فتُستبدل.
alice = Dict.fromList [ ( "Alice", 0 ) ]
aliceAndBob = Dict.insert "Bob" 1 alice --> Dict.fromList [ ( "Alice", 0 ), ( "Bob", 1 ) ]
aliceAndAlice = Dict.insert "Alice" 1 alice --> Dict.fromList [ ( "Alice", 1 ) ]
يمكن تحديث العناصر باستخدام update.
إذا لم يكن المفتاح موجودًا، فستُستدعى دالة التحديث بالقيمة Nothing.
alice = Dict.fromList [ ( 0, "Alice" ) ]
aliceUpperCase = Dict.update 0 (Maybe.map String.toUpper) alice --> Dict.fromList [ ( 0, "ALICE" ) ]
aliceNoCase = Dict.update 0 (\_ -> Nothing) alice --> Dict.empty
bobUpperCase = Dict.update 1 (\_ -> Just "BOB") alice --> Dict.fromList [ ( 0, "Alice" ), ( 1, "BOB" ) ]
bobNoCase = Dict.update 1 (\_ -> Nothing) alice --> Dict.fromList [ ( 0, "Alice" ) ]
يمكن إزالة العناصر باستخدام remove.
إذا لم يكن المفتاح موجودًا، فلن يحدث أي تغيير.
alice = Dict.fromList [ ( 0, "Alice" ) ]
stillAlice = Dict.remove 1 --> ( 0, "Alice" )
empty = Dict.remove 0 alice --> Dict.empty
يمكن تحويل مصفوفة من أزواج المفتاح والقيمة إلى قاموس باستخدام fromList.
alice = Dict.fromList [ ( 0, "Bob" ), ( 0, "Alice" ) ]
--> True Dict.fromList [ ( 0, "Alice" ) ]
يمكن تحويل العناصر إلى مصفوفة باستخدام toList.
وتُرتَّب المصفوفة حسب المفاتيح.
aliceAndBob = Dict.fromList [ ( 1, "Alice" ), ( 0, "Bob" ) ]
bobAndAlice = Dict.toList aliceAndBob
--> [ ( 0, "Bob" ), ( 1, "Alice" ) ]
يمكن إزالة عدة عناصر باستخدام filter.
aliceAndBob = Dict.fromList [ ( "Alice", 1 ), ( "Bob", 0 ) ]
bob = Dict.filter (\name count -> name == "Bob") aliceAndBob --> Dict.fromList [ ( "Bob", 0 ) ]
يمكن تحويل العناصر باستخدام map.
alice = Dict.fromList [ ( "Alice", 0 ) ]
empty = Dict.map (\player count -> count + 1) alice --> Dict.fromList [ ( "Alice", 1 ) ]
يمكن دمج القواميس أو تحويلها باستخدام merge.
aliceAndBob = Dict.fromList [ ( "Alice", 1 ), ( "Bob", 1 ) ]
bobAndCedd = Dict.fromList [ ( "Bob", 1 ), ( "Cedd", 1 ) ]
firstDictCountsDouble = Dict.merge
-- when only in aliceAndBob
(\name count mergedCounts -> Dict.insert name (2 * count) mergedCounts)
-- when in aliceAndBob and bobAndCedd
(\name aliceAndBobCount bobAndCeddCount mergedCounts -> Dict.insert name (2 * aliceAndBobCount + bobAndCeddCount) mergedCounts)
-- when only in bobAndCedd
(\name count mergedCounts -> Dict.insert name count mergedCounts)
-- the two dicts to merge
aliceAndBob
bobAndCedd
-- the initial state of the merge
Dict.empty
--> Dict.fromList [ ( "Alice", 2 ), ( "Bob", 3 ), ( "Cedd", 1 ) ]
أي دالة أو عامل يبدو أنه يعدّل القاموس (مثل إضافة عنصر)، فإنه يُرجع في الواقع قاموسًا جديدًا. وعادةً لا يمثّل الأداء مشكلة، لأن طريقة التنفيذ تمنع عمليات التخصيص أو النسخ غير الضرورية.
في Elm، من الأفضل عمومًا استخدام تجريدات ذات مستوى أعلى، مثل Dict.map وDict.filter وDict.merge، بدلًا من تجريدات ذات مستوى أدنى مثل Dict.get وDict.remove، مع أن الأمر يعتمد بالطبع على السياق.
مهمتك هي أن تأخذ قائمة بمسجّلي الأهداف في مباراة، وتحصي عدد الأهداف التي سجّلها كل لاعب.
PlayerName هو اسم مستعار للنوع String، لجعل الكود أسهل في القراءة، ولتمييز هذا الاستخدام لـ String عن الاستخدامات الأخرى لـ String.
أولًا، نفّذ updateGoalCountForPlayer لتهيئة عدد أهداف اللاعب أو زيادته.
ثم نفّذ دالة aggregateScorers لإحصاء عدد الأهداف التي سجّلها كل لاعب، باستخدام updateGoalCountForPlayer.
تأخذ هذه الدالة List PlayerName (أسماء اللاعبين الذين سجّلوا الأهداف، وقد تحتوي على أسماء لاعبين مكرّرة)، وتُرجع Dict PlayerName Int يحتوي على جميع اللاعبين في القائمة مع عدد الأهداف التي سجّلوها.
aggregateScorers [ "Betty", "Cedd", "Betty" ]
--> Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ]
نفّذ دالة removeInsignificantPlayers لاستبعاد اللاعبين الذين سجّلوا أهدافًا أقل من العتبة.
removeInsignificantPlayers 2 (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> Dict.fromList [ ( "Betty", 2 ) ]
نفّذ دالة resetPlayerGoalCount لإعادة تعيين عدد الأهداف المسجّلة للاعب إلى صفر.
resetPlayerGoalCount "Cedd" (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 0 ) ]
نفّذ دالة formatPlayer لتنسيق عدد الأهداف للاعب واحد على شكل سلسلة نصية. إذا لم يكن اللاعب موجودًا في القاموس، فافترض أن عدد أهدافه صفر.
formatPlayer "Betty" (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> "Betty: 2"
نفّذ دالة formatPlayers لتنسيق عدد الأهداف لجميع اللاعبين على شكل سلسلة نصية. يجب ترتيب اللاعبين حسب اسم اللاعب.
formatPlayers (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> "Betty: 2, Cedd: 1"
نفّذ دالة combineGames، مع إحصاء العدد الإجمالي للأهداف التي سجّلها كل لاعب في المباراتين.
combine Games
(Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
(Dict.fromList [ ( "Betty", 2 ), ( "Mario", 3 ) ] )
--> Dict.fromList [ ( "Betty", 4 ), ( "Cedd", 1 ), ( "Mario", 3 ) ]
سجّل في Exercism لتتعلّم وتتقن Elm عبر 28 مفهومًا110 تمارين، وإرشاد بشري حقيقي، وكل ذلك مجانًا.