Карта
Карты — это основная структура данных типа «ключ-значение» в Elixir.
Карты можно создать с помощью синтаксиса %{}, а пары «ключ-значение» можно выразить как key => value:
iex> %{}
%{}
iex> %{"one" => :two, 3 => "four"}
%{3 => "four", "one" => :two}
Пары «ключ-значение» в карте не упорядочены (поэтому отпечатанная карта в примере выше имеет другой порядок, чем созданная карта).
Карты не накладывают никаких ограничений на тип ключа: ключом в карте может быть всё. Как структура «ключ-значение», карты не допускают дублирования ключей. Ключи сравниваются с помощью оператора точного равенства (===/2). Если в литерале карты определены коллидирующие ключи, приоритет имеет последний.
Когда ключ в паре «ключ-значение» является атомом, можно использовать сокращённый синтаксис key: value (как и во многих других специальных формах), при условии, что пары «ключ-значение» помещаются в конец:
iex> %{"hello" => "world", a: 1, b: 2}
%{:a => 1, :b => 2, "hello" => "world"}
К ключам карт можно получить доступ с помощью некоторых функций в этом модуле (например, Map.get/3 или Map.fetch/2) или с помощью синтаксиса map[], предоставленного модулем Access:
iex> map = %{a: 1, b: 2}
iex> Map.fetch(map, :a)
{:ok, 1}
iex> map[:b]
2
iex> map["non_existing_key"]
nil
Для доступа к ключам-атомам можно также map.key. Обратите внимание, что, в то время как map[key] вернёт nil если map не содержит key, map.key вызовет исключение, если map не содержит ключ :key.
iex> map = %{foo: "bar", baz: "bong"}
iex> map.foo
"bar"
iex> map.non_existing_key
** (KeyError) key :non_existing_key not found in: %{baz: "bong", foo: "bar"}
Два синтаксиса для доступа к ключам раскрывают двойственную природу карт. Синтаксис map[key] используется для динамически созданных карт, которые могут содержать любой ключ любого типа. map.key используется с картами, которые содержат предопределённый набор ключей-атомов, которые ожидаются всегда присутствовать. Структуры, определённые с помощью defstruct/1, являются одним примером таких «статичных карт», где ключи также можно проверить на этапе компиляции.
На картах можно выполнять сопоставление с шаблонами. Если карта находится в левой части сопоставления с шаблоном, она будет соответствовать, если карта в правой части содержит ключи в левой части и их значения совпадают со значениями в левой части. Это означает, что пустая карта соответствует любой карте.
iex> %{} = %{foo: "bar"}
%{foo: "bar"}
iex> %{a: a} = %{:a => 1, "b" => 2, [:c, :e, :e] => 3}
iex> a
1
iex> %{:c => 3} = %{:a => 1, 2 => :b}
** (MatchError) no match of right hand side value: %{2 => :b, :a => 1}
Переменные могут использоваться в качестве ключей карты как при записи литералов карт, так и при сопоставлении:
iex> n = 1
1
iex> %{n => :one}
%{1 => :one}
iex> %{^n => :one} = %{1 => :one, 2 => :two, 3 => :three}
%{1 => :one, 2 => :two, 3 => :three}
Карты также поддерживают специальный синтаксис обновления для обновления значения, хранящегося под существующими атомными ключами:
iex> map = %{one: 1, two: 2}
iex> %{map | one: "one"}
%{one: "one", two: 2}
iex> %{map | three: 3}
** (KeyError) key :three not found
Функции в этом модуле, которым нужно найти определённый ключ, работают за логарифмическое время. Это означает, что время поиска ключей растёт по мере роста карты, но не прямо пропорционально размеру карты. По сравнению с поиском элемента в списке, это работает лучше, так как у списков линейная временная сложность. Некоторые функции, такие как keys/1 и values/1, выполняются за линейное время, потому что им нужно обратиться ко всем элементам карты.
Карты также реализуют протокол Enumerable, поэтому многие функции для работы с картами находятся в модуле Enum. Кроме того, следующие функции для карт находятся в Kernel:
Краткое описание
Типы
Функции
- delete(map, key)
Удаляет запись в
mapдля конкретногоkey.- drop(map, keys)
Удаляет указанные
keysизmap.- equal?(map1, map2)
Проверяет, равны ли две карты.
- fetch(map, key)
Извлекает значение для конкретного
keyв заданнойmap.- fetch!(map, key)
Извлекает значение для конкретного
keyв заданнойmap, вызывая ошибку, еслиmapне содержитkey.- from_struct(struct)
Преобразует
structв карту.- get(map, key, default \\ nil)
Получает значение для указанного
keyвmap.- get_and_update(map, key, fun)
Получает значение из
keyи обновляет его, всё в одном проходе.- get_and_update!(map, key, fun)
Получает значение из
keyи обновляет его. Вызывает исключение, если нетkey.- get_lazy(map, key, fun)
Получает значение для указанного
keyвmap.- has_key?(map, key)
Возвращает значение, если указанный
keyсуществует в заданнойmap.- keys(map)
Возвращает все ключи из
map.- merge(map1, map2)
Объединяет две карты в одну.
- merge(map1, map2, fun)
Объединяет две карты в одну, разрешая конфликты с помощью указанной
fun.- new()
Возвращает новую пустую карту.
- new(enumerable)
Создаёт карту из
enumerable.- new(enumerable, transform)
Создаёт карту из
enumerableс помощью заданной функции преобразования.- pop(map, key, default \\ nil)
Возвращает и удаляет значение, связанное с
keyвmap.- pop!(map, key)
Возвращает и удаляет значение, связанное с
keyвmapили вызывает исключение, еслиkeyотсутствует.- pop_lazy(map, key, fun)
Лениво возвращает и удаляет значение, связанное с
keyвmap.- put(map, key, value)
Помещает указанное
valueподkeyвmap.- put_new(map, key, value)
Помещает заданное
valueподkeyтолько если записьkeyещё не существует вmap.- put_new_lazy(map, key, fun)
Вычисляет
funи помещает результат подkeyвmapтолько еслиkeyещё не присутствует.- replace!(map, key, value)
Изменяет значение, хранящееся под
keyнаvalue, но только если записьkeyуже существует вmap.- split(map, keys)
Взять все записи, соответствующие заданным
keysвmapи извлечь их в отдельную карту.- take(map, keys)
Возвращает новую карту со всеми парами «ключ-значение» в
mapгде ключ находится вkeys.- to_list(map)
Преобразует
mapв список.- update(map, key, initial, fun)
Обновляет
keyвmapс помощью данной функции.- update!(map, key, fun)
Обновляет
keyс помощью заданной функции.- values(map)
Возвращает все значения из
map.
Типы
key()
Характеристики
key() :: any()
value()
Характеристики
value() :: any()
Функции
delete(map, key)
Спецификации
delete(map(), key()) :: map()
Удаляет запись в map для определенного key.
Если key не существует, возвращает map без изменений.
Встраивается компилятором.
Примеры
iex> Map.delete(%{a: 1, b: 2}, :a)
%{b: 2}
iex> Map.delete(%{b: 2}, :a)
%{b: 2} drop(map, keys)
Спецификации
drop(map(), [key()]) :: map()
Удаляет указанные keys из map.
Если keys содержит ключи, которых нет в map, они просто игнорируются.
Примеры
iex> Map.drop(%{a: 1, b: 2, c: 3}, [:b, :d])
%{a: 1, c: 3} equal?(map1, map2)
Спецификации
equal?(map(), map()) :: boolean()
Проверяет, равны ли две карты.
Две карты считаются равными, если они содержат одинаковые ключи и эти ключи содержат одинаковые значения.
Примеры
iex> Map.equal?(%{a: 1, b: 2}, %{b: 2, a: 1})
true
iex> Map.equal?(%{a: 1, b: 2}, %{b: 1, a: 2})
false fetch(map, key)
Спецификации
fetch(map(), key()) :: {:ok, value()} | :error Извлекает значение для определенного key в заданной map.
Если map содержит указанный key со значением value, то {:ok, value} возвращается. Если map не содержит key, возвращается :error.
Встраивается компилятором.
Примеры
iex> Map.fetch(%{a: 1}, :a)
{:ok, 1}
iex> Map.fetch(%{a: 1}, :b)
:error fetch!(map, key)
Спецификации
fetch!(map(), key()) :: value()
Извлекает значение для определенного key в данной map, вызывая ошибку, если map не содержит key.
Если map содержит данный key, возвращается соответствующее значение. Если map не содержит key, генерируется исключение KeyError.
Встраивается компилятором.
Примеры
iex> Map.fetch!(%{a: 1}, :a)
1 from_struct(struct)
Спецификации
from_struct(atom() | struct()) :: map()
Преобразует struct в карту.
Принимает модуль структуры или саму структуру и просто удаляет поле __struct__ из данной структуры или из новой структуры, сгенерированной из данного модуля.
Пример
defmodule User do
defstruct [:name]
end
Map.from_struct(User)
#=> %{name: nil}
Map.from_struct(%User{name: "john"})
#=> %{name: "john"} get(map, key, default \\ nil)
Спецификации
get(map(), key(), value()) :: value()
Получает значение для определенного key в map.
Если key присутствует в map со значением value, возвращается value. В противном случае возвращается default.
Если default не предоставлено, используется nil.
Примеры
iex> Map.get(%{}, :a)
nil
iex> Map.get(%{a: 1}, :a)
1
iex> Map.get(%{a: 1}, :b)
nil
iex> Map.get(%{a: 1}, :b, 3)
3 get_and_update(map, key, fun)
Спецификации
get_and_update(map(), key(), (value() -> {get, value()} | :pop)) :: {get, map()}
when get: term() Получает значение из key и обновляет его, все в одном проходе.
fun вызывается с текущим значением по ключу key в map (или nil если key отсутствует в map) и должно вернуть кортеж из двух элементов: значение "get" (извлеченное значение, которое можно обработать перед возвратом) и новое значение для хранения по ключу key в результирующей новой карте. fun также может вернуть :pop, что означает, что текущее значение должно быть удалено из map и возвращено (что делает эту функцию похожей на Map.pop(map, key)).
Возвращаемое значение представляет собой кортеж со значением "get", возвращённым функцией fun, и новой картой с обновлённым значением по ключу key.
Примеры
iex> Map.get_and_update(%{a: 1}, :a, fn current_value ->
...> {current_value, "new value!"}
...> end)
{1, %{a: "new value!"}}
iex> Map.get_and_update(%{a: 1}, :b, fn current_value ->
...> {current_value, "new value!"}
...> end)
{nil, %{b: "new value!", a: 1}}
iex> Map.get_and_update(%{a: 1}, :a, fn _ -> :pop end)
{1, %{}}
iex> Map.get_and_update(%{a: 1}, :b, fn _ -> :pop end)
{nil, %{a: 1}} get_and_update!(map, key, fun)
Спецификации
get_and_update!(map(), key(), (value() -> {get, value()} | :pop)) ::
{get, map()}
when get: term() Получает значение из key и обновляет его. Вызывает исключение, если ключа key нет.
Поведение точно такое же, как у get_and_update/3, но генерирует исключение KeyError, если key отсутствует в map.
Примеры
iex> Map.get_and_update!(%{a: 1}, :a, fn current_value ->
...> {current_value, "new value!"}
...> end)
{1, %{a: "new value!"}}
iex> Map.get_and_update!(%{a: 1}, :b, fn current_value ->
...> {current_value, "new value!"}
...> end)
** (KeyError) key :b not found in: %{a: 1}
iex> Map.get_and_update!(%{a: 1}, :a, fn _ ->
...> :pop
...> end)
{1, %{}} get_lazy(map, key, fun)
Спецификации
get_lazy(map(), key(), (() -> value())) :: value()
Получает значение для определенного key в map.
Если key присутствует в map со значением value, возвращается value. В противном случае, вычисляется fun и возвращается результат.
Это полезно, если значение по умолчанию очень дорого вычисляется или сложно настраивать и разворачивать заново.
Примеры
iex> map = %{a: 1}
iex> fun = fn ->
...> # some expensive operation here
...> 13
...> end
iex> Map.get_lazy(map, :a, fun)
1
iex> Map.get_lazy(map, :b, fun)
13 has_key?(map, key)
Спецификации
has_key?(map(), key()) :: boolean()
Возвращает, существует ли данный key в данной map.
Встраивается компилятором.
Примеры
iex> Map.has_key?(%{a: 1}, :a)
true
iex> Map.has_key?(%{a: 1}, :b)
false keys(map)
Спецификации
keys(map()) :: [key()]
Возвращает все ключи из map.
Встраивается компилятором.
Примеры
iex> Map.keys(%{a: 1, b: 2})
[:a, :b] merge(map1, map2)
Спецификации
merge(map(), map()) :: map()
Объединяет две карты в одну.
Все ключи из map2 будут добавлены в map1, перезаписывая любые существующие (т.е., ключи из map2 имеют "преимущество" перед ключами из map1).
Если у вас есть структура, и вы хотите объединить набор ключей в структуру, не используйте эту функцию, так как она объединит все ключи справа в структуру, даже если ключ не является частью структуры. Используйте вместо этого Kernel.struct/2.
Встраивается компилятором.
Примеры
iex> Map.merge(%{a: 1, b: 2}, %{a: 3, d: 4})
%{a: 3, b: 2, d: 4} merge(map1, map2, fun)
Спецификации
merge(map(), map(), (key(), value(), value() -> value())) :: map()
Объединяет две карты в одну, разрешая конфликты с помощью заданной функции fun.
Все ключи из map2 будут добавлены в map1. Данная функция будет вызвана при наличии дублирующихся ключей; её аргументами являются key (дублирующийся ключ), value1 (значение key в map1 ), и value2 (значение key в map2). Значение, возвращаемое fun, используется в качестве значения по ключу key в результирующей карте.
Примеры
iex> Map.merge(%{a: 1, b: 2}, %{a: 3, d: 4}, fn _k, v1, v2 ->
...> v1 + v2
...> end)
%{a: 4, b: 2, d: 4} new()
Спецификации
new() :: map()
Возвращает новую пустую карту.
Примеры
iex> Map.new()
%{} new(enumerable)
Спецификации
new(Enumerable.t()) :: map()
Создаёт карту из перечисляемого enumerable.
Дублирующиеся ключи удаляются; сохраняется последнее вхождение.
Примеры
iex> Map.new([{:b, 1}, {:a, 2}])
%{a: 2, b: 1}
iex> Map.new(a: 1, a: 2, a: 3)
%{a: 3} new(enumerable, transform)
Спецификации
new(Enumerable.t(), (term() -> {key(), value()})) :: map() Создаёт карту из перечисляемого enumerable с помощью заданной функции преобразования.
Дублирующиеся ключи удаляются; сохраняется последнее вхождение.
Примеры
iex> Map.new([:a, :b], fn x -> {x, x} end)
%{a: :a, b: :b} pop(map, key, default \\ nil)
Спецификации
pop(map(), key(), value()) :: {value(), map()} Возвращает и удаляет значение, связанное с ключом key в map.
Если key присутствует в map со значением value, возвращается {value, new_map}, где new_map — результат удаления ключа key из map . Если key не присутствует в map, возвращается {default, map}.
Примеры
iex> Map.pop(%{a: 1}, :a)
{1, %{}}
iex> Map.pop(%{a: 1}, :b)
{nil, %{a: 1}}
iex> Map.pop(%{a: 1}, :b, 3)
{3, %{a: 1}} pop!(map, key)
Характеристики
pop!(map(), key()) :: {value(), map()} Возвращает и удаляет значение, связанное с key в map или вызывает исключение, если key отсутствует.
Ведёт себя так же, как pop/3, но вызывает исключение, если key отсутствует в map.
Примеры
iex> Map.pop!(%{a: 1}, :a)
{1, %{}}
iex> Map.pop!(%{a: 1, b: 2}, :a)
{1, %{b: 2}}
iex> Map.pop!(%{a: 1}, :b)
** (KeyError) key :b not found in: %{a: 1} pop_lazy(map, key, fun)
Характеристики
pop_lazy(map(), key(), (() -> value())) :: {value(), map()} Лениво возвращает и удаляет значение, связанное с key в map.
Если key присутствует в map со значением value, возвращается {value, new_map}, где new_map — результат удаления key из map. Если key отсутствует в map, возвращается {fun_result, map}, где fun_result — результат применения fun.
Это полезно, если значение по умолчанию очень дорого вычислять или в целом сложно настраивать и отключать.
Примеры
iex> map = %{a: 1}
iex> fun = fn ->
...> # some expensive operation here
...> 13
...> end
iex> Map.pop_lazy(map, :a, fun)
{1, %{}}
iex> Map.pop_lazy(map, :b, fun)
{13, %{a: 1}} put(map, key, value)
Характеристики
put(map(), key(), value()) :: map()
Помещает заданное value под key в map.
Встроено компилятором.
Примеры
iex> Map.put(%{a: 1}, :b, 2)
%{a: 1, b: 2}
iex> Map.put(%{a: 1, b: 2}, :a, 3)
%{a: 3, b: 2} put_new(map, key, value)
Характеристики
put_new(map(), key(), value()) :: map()
Помещает заданное value под key, если запись key ещё не существует в map.
Примеры
iex> Map.put_new(%{a: 1}, :b, 2)
%{a: 1, b: 2}
iex> Map.put_new(%{a: 1, b: 2}, :a, 3)
%{a: 1, b: 2} put_new_lazy(map, key, fun)
Характеристики
put_new_lazy(map(), key(), (() -> value())) :: map()
Вычисляет fun и помещает результат под key в map, если key ещё не существует.
Эта функция полезна в случае, когда вы хотите вычислить значение для размещения под key только если key не существует, например, когда значение дорого вычисляется или сложно настраивать и отключать.
Примеры
iex> map = %{a: 1}
iex> fun = fn ->
...> # some expensive operation here
...> 3
...> end
iex> Map.put_new_lazy(map, :a, fun)
%{a: 1}
iex> Map.put_new_lazy(map, :b, fun)
%{a: 1, b: 3} replace!(map, key, value)
Характеристики
replace!(map(), key(), value()) :: map()
Изменяет значение, хранящееся под key, на value, но только если запись key уже существует в map.
Если key отсутствует в map, генерируется исключение KeyError.
Встроено компилятором.
Примеры
iex> Map.replace!(%{a: 1, b: 2}, :a, 3)
%{a: 3, b: 2}
iex> Map.replace!(%{a: 1}, :b, 2)
** (KeyError) key :b not found in: %{a: 1} split(map, keys)
Характеристики
split(map(), [key()]) :: {map(), map()} Берёт все записи, соответствующие заданным keys в map и извлекает их в отдельный словарь.
Возвращает кортеж с новым словарем и старым словарем с удалёнными ключами.
Ключи, для которых нет записей в map игнорируются.
Примеры
iex> Map.split(%{a: 1, b: 2, c: 3}, [:a, :c, :e])
{%{a: 1, c: 3}, %{b: 2}} take(map, keys)
Характеристики
take(map(), [key()]) :: map()
Возвращает новый словарь со всеми парами ключ-значение в map, где ключ находится в keys.
Если keys содержит ключи, которых нет в map, они просто игнорируются.
Примеры
iex> Map.take(%{a: 1, b: 2, c: 3}, [:a, :c, :e])
%{a: 1, c: 3} to_list(map)
Характеристики
to_list(map()) :: [{term(), term()}] Преобразует map в список.
Каждая пара ключ-значение в словаре преобразуется в двухэлементный кортеж {key, value} в результирующем списке.
Встроено компилятором.
Примеры
iex> Map.to_list(%{a: 1})
[a: 1]
iex> Map.to_list(%{1 => 2})
[{1, 2}] update(map, key, initial, fun)
Характеристики
update(map(), key(), value(), (value() -> value())) :: map()
Обновляет key в map с помощью заданной функции.
Если key присутствует в map со значением value, fun вызывается с аргументом value и её результат используется в качестве нового значения key Если key отсутствует в map, initial вставляется в качестве значения key. Начальное значение не будет передано в функцию обновления.
Примеры
iex> Map.update(%{a: 1}, :a, 13, &(&1 * 2))
%{a: 2}
iex> Map.update(%{a: 1}, :b, 11, &(&1 * 2))
%{a: 1, b: 11} update!(map, key, fun)
Характеристики
update!(map(), key(), (value() -> value())) :: map()
Обновляет key с помощью заданной функции.
Если key присутствует в map со значением value, fun вызывается с аргументом value и её результат используется в качестве нового значения key. Если key отсутствует в map, генерируется исключение KeyError.
Примеры
iex> Map.update!(%{a: 1}, :a, &(&1 * 2))
%{a: 2}
iex> Map.update!(%{a: 1}, :b, &(&1 * 2))
** (KeyError) key :b not found in: %{a: 1} values(map)
Характеристики
values(map()) :: [value()]
Возвращает все значения из map.
Встроено компилятором.
Примеры
iex> Map.values(%{a: 1, b: 2})
[1, 2]
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.10.4/Map.html