مسیرها
/
Elm
Elm
/
تمرین‌ها
/
گل‌زنان برتر
گل‌زنان برتر

گل‌زنان برتر

تمرین یادگیری

مقدمه

Dict

در 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 به‌روزرسانی کرد. اگر کلید وجود نداشته باشد، تابع 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.get و Dict.remove از انتزاع‌های سطح بالا مثل Dict.map، Dict.filter و Dict.merge استفاده کنید، هرچند البته این موضوع به بافت بستگی دارد.

دستورالعمل‌ها

وظیفه‌ی شما این است که فهرستی از گل‌زنان یک بازی را بگیرید و بشمارید که هر بازیکن چند گل زده است.

PlayerName یک نام مستعار نوع برای String است تا کد خواناتر شود و این کاربرد String از کاربردهای دیگرش متمایز شود.

1. تجمیع گل‌زنان

ابتدا updateGoalCountForPlayer را پیاده‌سازی کنید تا تعداد گل‌های یک بازیکن را مقداردهی اولیه کند یا یک واحد افزایش دهد. سپس تابع aggregateScorers را پیاده‌سازی کنید تا با استفاده از updateGoalCountForPlayer بشمارید که هر بازیکن چند گل زده است. این تابع یک List PlayerName می‌گیرد (اسم بازیکنانی که گل زده‌اند و می‌تواند شامل اسم‌های تکراری باشد) و یک Dict PlayerName Int برمی‌گرداند که شامل همه‌ی بازیکنان فهرست به همراه تعداد گل‌هایشان است.

aggregateScorers [ "Betty", "Cedd", "Betty" ]
--> Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ]

2. حذف بازیکنان کم‌اهمیت

تابع removeInsignificantPlayers را پیاده‌سازی کنید تا بازیکنانی را که کمتر از آستانه گل زده‌اند حذف کنید.

removeInsignificantPlayers 2 (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> Dict.fromList [ ( "Betty", 2 ) ]

3. بازنشانی تعداد گل بازیکن

تابع resetPlayerGoalCount را پیاده‌سازی کنید تا تعداد گل‌های زده‌شده‌ی یک بازیکن را به صفر بازنشانی کند.

resetPlayerGoalCount "Cedd" (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 0 ) ]

4. قالب‌بندی تعداد گل یک بازیکن

تابع formatPlayer را پیاده‌سازی کنید تا تعداد گل یک بازیکن را به‌صورت رشته قالب‌بندی کند. اگر بازیکن در دیکشنری وجود ندارد، فرض کنید تعداد گلش صفر است.

formatPlayer "Betty" (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> "Betty: 2"

5. قالب‌بندی تعداد گل همه‌ی بازیکنان

تابع formatPlayers را پیاده‌سازی کنید تا تعداد گل همه‌ی بازیکنان را به‌صورت رشته قالب‌بندی کند. بازیکنان باید بر اساس اسم بازیکن مرتب شوند.

formatPlayers (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> "Betty: 2, Cedd: 1"

6. ترکیب بازی‌ها

تابع combineGames را پیاده‌سازی کنید و تعداد کل گل‌هایی را که هر بازیکن در هر دو بازی زده است، بشمارید.

combine Games
  (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
  (Dict.fromList [ ( "Betty", 2 ), ( "Mario", 3 ) ] )
--> Dict.fromList [ ( "Betty", 4 ), ( "Cedd", 1 ), ( "Mario", 3 ) ]
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Elm Exercism

آماده‌اید گل‌زنان برتر را شروع کنید؟

در Exercism ثبت‌نام کنید تا Elm را همراه با 28 مفهوم110 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.