Elm-এ একটি Dict হলো শূন্য বা তার বেশি কী (key)-মান জোড়ার একটি অপরিবর্তনীয় ডিকশনারি।
ডিকশনারিগুলো 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 দিয়ে এলিমেন্টগুলো পাওয়া যায়।
যেহেতু একটি কী (key) ডিকশনারিতে থাকতেও পারে, না-ও থাকতে পারে, তাই ফলাফলটি একটি Maybe-তে মোড়ানো থাকে।
alice = Dict.fromList [ ( 0, "Alice" ) ]
keyExists = Dict.get 0 alice --> Just "Alice"
keyNotPresent = Dict.get 1 alice --> Nothing
insert দিয়ে এলিমেন্ট যোগ করা যায়।
যে কী (key)গুলো ইতিমধ্যে ডিকশনারিতে আছে, সেগুলোর এলিমেন্ট প্রতিস্থাপন করা হয়।
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 দিয়ে এলিমেন্ট আপডেট করা যায়।
কী (key)টি না থাকলে আপডেট ফাংশনটি 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 দিয়ে এলিমেন্ট মুছে ফেলা যায়।
কী (key)টি না থাকলে কোনো পরিবর্তন করা হয় না।
alice = Dict.fromList [ ( 0, "Alice" ) ]
stillAlice = Dict.remove 1 --> ( 0, "Alice" )
empty = Dict.remove 0 alice --> Dict.empty
fromList দিয়ে কী (key)-মান জোড়ার একটি অ্যারেকে ডিকশনারিতে রূপান্তর করা যায়।
alice = Dict.fromList [ ( 0, "Bob" ), ( 0, "Alice" ) ]
--> True Dict.fromList [ ( 0, "Alice" ) ]
toList দিয়ে এলিমেন্টগুলোকে একটি অ্যারেতে রূপান্তর করা যায়।
অ্যারাটি কী (key)গুলো অনুসারে সাজানো থাকে।
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টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।