Мапи в Elixir використовують для зберігання інформації у вигляді пар ключ-значення. В інших мовах їх також можуть називати асоціативними масивами (PHP), хешами (Perl 5, Raku) або словниками (Python).
Ключі та значення можуть бути будь-якого типу даних, але якщо ключ є атомом, ми можемо скористатися скороченим синтаксисом. Мапи не гарантують порядку своїх записів під час доступу до них або повернення.
Порожню мапу можна просто оголосити за допомогою %{}. Якщо ми хочемо додати елементи до літерала мапи, можемо скористатися двома формами:
# If the key is an atom:
%{atom_key: 1}
# If the key is a different type:
%{1 => :atom_value}
# You can even mix these if the atom form comes second:
%{"first_form" => :a, atom_form: :b}
Хоча канонічного формату немає, обираймо послідовний спосіб представлення пар ключ-значення.
Elixir надає багато функцій для роботи з мапами в модулі Map. Деякі функції модуля Map вимагають, щоб ми передали в них анонімну функцію, яка допомагає перетворити мапу.
В Elixir ми можемо визначати атрибути модуля, які потім можна використовувати як константи у своїх функціях.
defmodule Example do
# Defines the attribute as the value 1
@constant_number 1
def example_value() do
# Returns the value 1
@constant_number
end
end
Коли атрибути використовують для визначення констант модуля, ними може бути будь-який вираз, який можна обчислити під час компіляції. Після компіляції атрибути модуля стають недоступними, оскільки вони розкриваються під час компіляції, подібно до визначених макросів у таких мовах, як C.
У цій вправі ми реалізуємо спосіб відстежувати рекорди найпопулярнішої гри в місцевому залі ігрових автоматів.
Щоб створити нову мапу рекордів, визначте функцію HighScore.new/0, яка не приймає жодних аргументів і повертає нову порожню мапу рекордів.
HighScore.new()
# => %{}
Щоб додати гравця до мапи рекордів, визначте функцію HighScore.add_player/3, яка приймає 3 аргументи:
Збережіть типове початкове значення рахунку в атрибуті модуля. Воно ще знадобиться.
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "Dave Thomas")
# => %{"Dave Thomas" => 0}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"Dave Thomas" => 0, "José Valim"=> 486_373}
Щоб видалити гравця з мапи рекордів, визначте функцію HighScore.remove_player/2, яка приймає 2 аргументи:
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "Dave Thomas")
# => %{"Dave Thomas" => 0}
score_map = HighScore.remove_player(score_map, "Dave Thomas")
# => %{}
Щоб скинути рахунок гравця, визначте функцію HighScore.reset_score/2, яка приймає 2 аргументи:
Функція повинна також працювати, якщо гравець не має рахунку.
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"José Valim"=> 486_373}
score_map = HighScore.reset_score(score_map, "José Valim")
# => %{"José Valim"=> 0}
Щоб оновити рахунок гравця, додавши до попереднього рахунку, визначте функцію HighScore.update_score/3, яка приймає 3 аргументи:
Функція повинна також працювати, якщо гравець не має попереднього рахунку: вважайте, що попередній рахунок дорівнює 0.
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"José Valim"=> 486_373}
score_map = HighScore.update_score(score_map, "José Valim", 5)
# => %{"José Valim"=> 486_378}
Щоб отримати список гравців, визначте функцію HighScore.get_players/1, яка приймає 1 аргумент:
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "Dave Thomas", 2_374)
# => %{"Dave Thomas" => 2_374}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"Dave Thomas" => 2_374, "José Valim"=> 486_373}
HighScore.get_players(score_map)
# => ["Dave Thomas", "José Valim"]
Зареєструйтеся на Exercism, щоб вивчати й опановувати Elixir, а також 58 концепцій168 вправ та справжнє наставництво від людей, і все це безкоштовно.