Elixir: Словари
Словарь (Map) хранит пары ключ-значение. Это еще одна динамическая структура данных в которую можно добавлять и удалять элементы.
Словарь создается с помощью конструкции %{key1 => value1, key2 => value2}. Для обращения по ключу используются квадратные скобки:
my_map = %{"a" => 1, "b" => 2}
my_map["a"] # 1
my_map["b"] # 2Часто в качестве ключей используют атомы:
other_map = %{:a => 1, :b => 2}
other_map[:a] # 1
other_map[:b] # 2Для ключей атомов (и только в этом случае) можно использовать синтаксический сахар:
other_map = %{a: 1, b: 2}
other_map.a # 1
other_map.b # 2Обращение через квадратные скобки и обращение через точку работают по-разному в случае, когда ключ отсутствует в словаре:
other_map[:c] # nil
other_map.c # ** (KeyError) key :c not found in: %{a: 1, b: 2}Как видим, в первом случае возвращается значение nil, а во втором случае генерируется исключение.
Функция Map.get работает так же, как обращение через квадратные скобки. Но она позволяет указать дефолтное значение для отсутствующего ключа:
Map.get(other_map, :a) # 1
Map.get(other_map, :c) # nil
Map.get(other_map, :c, 42) # 42Для добавления нового ключа или для изменения значения существующего ключа используется функция Map.put:
Map.put(other_map, :c, 42) # %{a: 1, b: 2, c: 42}
Map.put(other_map, :a, 42) # %{a: 42, b: 2}Словарь, как и все остальные значения в Эликсир, является иммутабельным. Поэтому функция Map.put возвращает новый словарь, а старый остается неизменным:
new_map = Map.put(other_map, :c, 42)
IO.puts(inspect(new_map)) # => %{a: 1, b: 2, c: 42}
IO.puts(inspect(other_map)) # => %{a: 1, b: 2}Для изменения значения существующего ключа есть синтаксический сахар:
%{other_map | :a => 42} # %{a: 42, b: 2}
%{other_map | :a => 42 , :b => 43} # %{a: 42, b: 43}Такой синтаксис удобен тем, что позволяет изменять несколько ключей сразу.
А добавить новый ключ этот синтаксис не позволяет:
%{other_map | :c => 42} # ** (KeyError) key :c not found in: %{a: 1, b: 2}Для удаления ключа используется функция Map.delete. Она тоже возвращает новый словарь, а старый остается неизменным:
Map.delete(other_map, :a) # %{b: 2}Задание
Реализуйте функцию keys_sum, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает сумму значений. Если ключа в словаре нет, то соответствующее значение не учитывается.
Реализуйте функцию keys_product, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает произведение значений. Если ключа в словаре нет, то соответствующее значение не учитывается.
Реализуйте функцию copy_key, которая принимает два словаря, ключ, и значение по умолчанию. По ключу нужно извлечь значение из первого словаря и вставить во второй словарь. Если в первом словаре нет такого ключа, то во второй словарь нужно вставить значение по умолчанию. Если во втором словаре уже есть такой ключ, то его значение меняется.
map = %{a: 1, b: 2, c: 42}
Solution.keys_sum(map, :a, :b)
# => 3
Solution.keys_sum(map, :a, :c)
# => 43
Solution.keys_sum(map, :c, :b)
# => 44
map = %{one: 1, five: 5, ten: 10}
Solution.keys_product(map, :one, :five)
# => 5
Solution.keys_product(map, :five, :ten)
# => 50
Solution.keys_product(map, :two, :ten)
# => 10
map1 = %{a: 1, b: 2}
map2 = %{c: 3, d: 4}
Solution.copy_key(map1, map2, :a, 42)
# => %{c: 3, d: 4, a: 1}
Solution.copy_key(map1, map2, :b, 42)
# => %{c: 3, d: 4, b: 2}
Solution.copy_key(map2, map1, :d, 42)
# => %{a: 1, b: 2, d: 4}
Solution.copy_key(map2, map1, :e, 42)
# => %{a: 1, b: 2, e: 42}Полезное
Elixir: Словари
Словарь (Map) хранит пары ключ-значение. Это еще одна динамическая структура данных в которую можно добавлять и удалять элементы.
Словарь создается с помощью конструкции %{key1 => value1, key2 => value2}. Для обращения по ключу используются квадратные скобки:
my_map = %{"a" => 1, "b" => 2}
my_map["a"] # 1
my_map["b"] # 2Часто в качестве ключей используют атомы:
other_map = %{:a => 1, :b => 2}
other_map[:a] # 1
other_map[:b] # 2Для ключей атомов (и только в этом случае) можно использовать синтаксический сахар:
other_map = %{a: 1, b: 2}
other_map.a # 1
other_map.b # 2Обращение через квадратные скобки и обращение через точку работают по-разному в случае, когда ключ отсутствует в словаре:
other_map[:c] # nil
other_map.c # ** (KeyError) key :c not found in: %{a: 1, b: 2}Как видим, в первом случае возвращается значение nil, а во втором случае генерируется исключение.
Функция Map.get работает так же, как обращение через квадратные скобки. Но она позволяет указать дефолтное значение для отсутствующего ключа:
Map.get(other_map, :a) # 1
Map.get(other_map, :c) # nil
Map.get(other_map, :c, 42) # 42Для добавления нового ключа или для изменения значения существующего ключа используется функция Map.put:
Map.put(other_map, :c, 42) # %{a: 1, b: 2, c: 42}
Map.put(other_map, :a, 42) # %{a: 42, b: 2}Словарь, как и все остальные значения в Эликсир, является иммутабельным. Поэтому функция Map.put возвращает новый словарь, а старый остается неизменным:
new_map = Map.put(other_map, :c, 42)
IO.puts(inspect(new_map)) # => %{a: 1, b: 2, c: 42}
IO.puts(inspect(other_map)) # => %{a: 1, b: 2}Для изменения значения существующего ключа есть синтаксический сахар:
%{other_map | :a => 42} # %{a: 42, b: 2}
%{other_map | :a => 42 , :b => 43} # %{a: 42, b: 43}Такой синтаксис удобен тем, что позволяет изменять несколько ключей сразу.
А добавить новый ключ этот синтаксис не позволяет:
%{other_map | :c => 42} # ** (KeyError) key :c not found in: %{a: 1, b: 2}Для удаления ключа используется функция Map.delete. Она тоже возвращает новый словарь, а старый остается неизменным:
Map.delete(other_map, :a) # %{b: 2}Задание
Реализуйте функцию keys_sum, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает сумму значений. Если ключа в словаре нет, то соответствующее значение не учитывается.
Реализуйте функцию keys_product, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает произведение значений. Если ключа в словаре нет, то соответствующее значение не учитывается.
Реализуйте функцию copy_key, которая принимает два словаря, ключ, и значение по умолчанию. По ключу нужно извлечь значение из первого словаря и вставить во второй словарь. Если в первом словаре нет такого ключа, то во второй словарь нужно вставить значение по умолчанию. Если во втором словаре уже есть такой ключ, то его значение меняется.
map = %{a: 1, b: 2, c: 42}
Solution.keys_sum(map, :a, :b)
# => 3
Solution.keys_sum(map, :a, :c)
# => 43
Solution.keys_sum(map, :c, :b)
# => 44
map = %{one: 1, five: 5, ten: 10}
Solution.keys_product(map, :one, :five)
# => 5
Solution.keys_product(map, :five, :ten)
# => 50
Solution.keys_product(map, :two, :ten)
# => 10
map1 = %{a: 1, b: 2}
map2 = %{c: 3, d: 4}
Solution.copy_key(map1, map2, :a, 42)
# => %{c: 3, d: 4, a: 1}
Solution.copy_key(map1, map2, :b, 42)
# => %{c: 3, d: 4, b: 2}
Solution.copy_key(map2, map1, :d, 42)
# => %{a: 1, b: 2, d: 4}
Solution.copy_key(map2, map1, :e, 42)
# => %{a: 1, b: 2, e: 42}Полезное
Ваше упражнение проверяется по этим тестам
defmodule Test do
use ExUnit.Case
import Solution
test "keys_sum" do
map = %{a: 1, b: 2, c: 42}
assert keys_sum(map, :a, :b) == 3
assert keys_sum(map, :a, :c) == 43
assert keys_sum(map, :c, :b) == 44
assert keys_sum(map, :a, :a) == 2
assert keys_sum(map, :a, :d) == 1
assert keys_sum(map, :d, :c) == 42
assert keys_sum(map, :d, :e) == 0
end
test "keys_product" do
map = %{one: 1, five: 5, ten: 10}
assert keys_product(map, :one, :five) == 5
assert keys_product(map, :one, :ten) == 10
assert keys_product(map, :five, :ten) == 50
assert keys_product(map, :five, :five) == 25
assert keys_product(map, :five, :two) == 5
assert keys_product(map, :two, :ten) == 10
assert keys_product(map, :two, :three) == 1
end
test "copy_key" do
map1 = %{a: 1, b: 2}
map2 = %{c: 3, d: 4}
assert copy_key(map1, map2, :a, 42) == %{c: 3, d: 4, a: 1}
assert copy_key(map1, map2, :b, 42) == %{c: 3, d: 4, b: 2}
assert copy_key(map1, map2, :e, 42) == %{c: 3, d: 4, e: 42}
assert copy_key(map1, map2, :c, 42) == %{c: 42, d: 4}
assert copy_key(map2, map1, :c, 42) == %{a: 1, b: 2, c: 3}
assert copy_key(map2, map1, :d, 42) == %{a: 1, b: 2, d: 4}
assert copy_key(map2, map1, :e, 42) == %{a: 1, b: 2, e: 42}
assert copy_key(map2, map1, :b, 42) == %{a: 1, b: 42}
end
endРешение учителя откроется через:
20:00
