Spec-Zone.ru › Elixir 1.13

Карта

Карты — это основная структура данных ключ-значение в Elixir.

Карты можно создавать с помощью синтаксиса %{}, а пары ключ-значение могут быть представлены как key => value:

iex> %{}
%{}
iex> %{"one" => :two, 3 => "four"}
%{3 => "four", "one" => :two}

Пары ключ-значение в карте не следуют никакому порядку (поэтому напечатанная карта в приведённом выше примере имеет другой порядок, чем карта, которая была создана).

Карты не накладывают никаких ограничений на тип ключа: любым значением может быть ключ в карте. Как структура ключ-значение, карты не допускают дублирования ключей. Ключи сравниваются с помощью оператора точного равенства (===/2). Если в литерале карты определяются коллидирующие ключи, то преобладает последний.

Когда ключ в паре ключ-значение — атом, можно использовать сокращённый синтаксис key: value (как и во многих других специальных формах):

iex> %{a: 1, b: 2}
%{a: 1, b: 2}

Если вы хотите смешать сокращённый синтаксис с =>, сокращённый синтаксис должен стоять в конце:

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 вызовет исключение KeyError, если карта map не содержит ключ :key, в отличие от map[:key], который вернёт nil.

map = %{foo: "bar", baz: "bong"}
map.foo
#=> "bar"
map.non_existing_key
** (KeyError) key :non_existing_key not found in: %{baz: "bong", foo: "bar"}

Примечание: не добавляйте скобки при доступе к полям, например, в data.key(). Если используются скобки, Elixir ожидает, что data будет атомом, представляющим модуль, и попытается вызвать функцию key/0 в нём.

Два синтаксиса для доступа к ключам раскрывают двойственную природу карт. Синтаксис 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

Но это вызовет исключение MatchError:

%{:c => 3} = %{:a => 1, 2 => :b}

Переменные могут использоваться в качестве ключей карт как при написании литералов карт, так и при сопоставлении:

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}

При обновлении ключа, которого нет в карте, будет вызвано исключение KeyError:

%{map | three: 3}

Функции в этом модуле, которые должны найти определённый ключ, работают за логарифмическое время. Это означает, что время, необходимое для поиска ключей, растёт вместе с ростом карты, но не прямо пропорционально размеру карты. По сравнению с поиском элемента в списке, это работает лучше, потому что списки имеют линейную сложность времени. Некоторые функции, такие как keys/1 и values/1, выполняются за линейное время, потому что им нужно получить доступ ко всем элементам карты.

Карты также реализуют протокол Enumerable, поэтому многие функции для работы с картами находятся в модуле Enum. Кроме того, следующие функции для карт находятся в Kernel:

  • map_size/1

Краткое описание

Типы

key()
value()

Функции

delete(map, key)

Удаляет запись в map для определенного key.

drop(map, keys)

Удаляет указанные keys из map.

equal?(map1, map2)

Проверяет, равны ли два словаря.

fetch!(map, key)

Извлекает значение для определенного key в данном map, с ошибкой, если map не содержит key.

fetch(map, key)

Извлекает значение для определенного key в данном map.

filter(map, fun)

Возвращает словарь, содержащий только те пары из map, для которых fun возвращает истинное значение.

from_struct(struct)

Преобразует struct в словарь.

get(map, key, default \\ nil)

Получает значение для определенного key в map.

get_and_update!(map, key, fun)

Получает значение из key и обновляет его, все в одном проходе. Вызывает исключение, если нет key.

get_and_update(map, key, fun)

Получает значение из 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)

Удаляет значение, связанное с key в map и возвращает значение и обновлённый словарь, или вызывает исключение, если key отсутствует.

pop(map, key, default \\ nil)

Удаляет значение, связанное с key в map и возвращает значение и обновлённый словарь.

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 ещё не присутствует.

reject(map, fun)

Возвращает словарь, исключая пары из map для которых fun возвращает истинное значение.

replace!(map, key, value)

Добавляет значение под key только если key уже существует в map.

replace(map, key, value)

Добавляет значение под key только если key уже существует в map.

split(map, keys)

Берёт все записи, соответствующие заданным keys в map и извлекает их в отдельный словарь.

take(map, keys)

Возвращает новый словарь со всеми парами ключ-значение в map где ключ находится в keys.

to_list(map)

Преобразует map в список.

update!(map, key, fun)

Обновляет key с помощью заданной функции.

update(map, key, default, fun)

Обновляет key в map с помощью заданной функции.

values(map)

Возвращает все значения из map.

Типы

key()Source

@type key() :: any()

value()Source

@type value() :: any()
END_OF_DOCUMENT_MARKER

Функции

delete(map, key)Source

@spec 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)Source

@spec 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)Source

@spec equal?(map(), map()) :: boolean()

Проверяет равенство двух карт.

Две карты считаются равными, если они содержат одинаковые ключи и эти ключи содержат одинаковые значения.

Эта функция существует для полноты, чтобы модули Map и Keyword предоставляли аналогичные API. На практике разработчики часто сравнивают карты, используя ==/2 или ===/2 напрямую.

Примеры

iex> Map.equal?(%{a: 1, b: 2}, %{b: 2, a: 1})
true
iex> Map.equal?(%{a: 1, b: 2}, %{b: 1, a: 2})
false

Сравнение ключей и значений выполняется с помощью ===/3, что означает, что целые числа не эквивалентны числам с плавающей точкой:

iex> Map.equal?(%{a: 1.0}, %{a: 1})
false

fetch!(map, key)Source

@spec fetch!(map(), key()) :: value()

Извлекает значение для определенного key в заданной map, возвращая ошибку, если map не содержит key.

Если map содержит key, возвращается соответствующее значение. Если map не содержит key, генерируется исключение KeyError.

Встроено компилятором.

Примеры

iex> Map.fetch!(%{a: 1}, :a)
1

fetch(map, key)Source

@spec fetch(map(), key()) :: {:ok, value()} | :error

Извлекает значение для указанного key в данной map.

Если map содержит указанное key, то возвращается его значение в виде {:ok, value}. Если map не содержит key, возвращается :error.

Встроено компилятором.

Примеры

iex> Map.fetch(%{a: 1}, :a)
{:ok, 1}
iex> Map.fetch(%{a: 1}, :b)
:error

filter(map, fun)Source

@spec filter(map(), ({key(), value()} -> as_boolean(term()))) :: map()

Возвращает карту, содержащую только те пары из map, для которых fun возвращает истинное значение.

fun получает ключ и значение каждого элемента в карте в виде пары «ключ-значение».

См. также reject/2, которое отбрасывает все элементы, где функция возвращает истинное значение.

Примечание: если вы обнаружите, что выполняете несколько вызовов Map.filter/2 и Map.reject/2 в конвейере, вероятно, эффективнее использовать Enum.map/2 и Enum.filter/2 и преобразовать в карту в конце, используя Map.new/1.

Примеры

iex> Map.filter(%{one: 1, two: 2, three: 3}, fn {_key, val} -> rem(val, 2) == 1 end)
%{one: 1, three: 3}

from_struct(struct)Source

@spec 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)Source

@spec get(map(), key(), value()) :: value()

Получает значение для указанного key в map.

Если key присутствует в map, возвращается его значение 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)Source

@spec get_and_update!(
  map(),
  key(),
  (value() | nil -> {current_value, new_value :: value()} | :pop)
) ::
  {current_value, map()}
when current_value: value()

Получает значение из 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_and_update(map, key, fun)Source

@spec get_and_update(
  map(),
  key(),
  (value() | nil -> {current_value, new_value :: value()} | :pop)
) ::
  {current_value, new_map :: map()}
when current_value: value()

Получает значение из key и обновляет его за один проход.

fun вызывается с текущим значением под key в map (или nil, если key не присутствует в map). Она должна вернуть кортеж из двух элементов: текущее значение (извлечённое значение, которое можно обработать перед возвращением) и новое значение, которое нужно сохранить под key в результирующей новой карте. fun также может вернуть :pop, что означает, что текущее значение должно быть удалено из map и возвращено (делая эту функцию похожей на Map.pop(map, key)).

Возвращаемое значение — кортеж из двух элементов: текущее значение, возвращённое 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, %{a: 1, b: "new value!"}}

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_lazy(map, key, fun)Source

@spec get_lazy(map(), key(), (() -> value())) :: value()

Получает значение для указанного key в map.

Если key присутствует в map, возвращается его значение 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)Source

@spec 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)Source

@spec keys(map()) :: [key()]

Возвращает все ключи из map.

Встроено компилятором.

Примеры

iex> Map.keys(%{a: 1, b: 2})
[:a, :b]

merge(map1, map2)Source

@spec 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}
END_OF_DOCUMENT_MARKER

merge(map1, map2, fun)Source

@spec 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()Source

@spec new() :: map()

Возвращает новую пустую карту.

Примеры

iex> Map.new()
%{}

new(enumerable)Source

@spec 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)Source

@spec 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)Source

@spec pop!(map(), key()) :: {value(), updated_map :: 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(map, key, default \\ nil)Source

@spec pop(map(), key(), default) :: {value(), updated_map :: map()} | {default, map()}
when default: value()

Удаляет значение, связанное с key в map и возвращает значение и обновлённую карту.

Если key присутствует в map, возвращается {value, updated_map}, где value — значение ключа, а updated_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_lazy(map, key, fun)Source

@spec pop_lazy(map(), key(), (() -> value())) :: {value(), map()}

Лениво возвращает и удаляет значение, связанное с key в map.

Если key присутствует в map, возвращается {value, new_map}, где value — значение ключа, а 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)Source

@spec 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)Source

@spec 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)Source

@spec 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}

reject(map, fun)Source

@spec reject(map(), ({key(), value()} -> as_boolean(term()))) :: map()

Возвращает карту, исключая пары из map, для которых fun возвращает истинное значение.

См. также filter/2.

Примеры

iex> Map.reject(%{one: 1, two: 2, three: 3}, fn {_key, val} -> rem(val, 2) == 1 end)
%{two: 2}

replace!(map, key, value)Source

@spec replace!(map(), key(), value()) :: map()

Устанавливает значение под key только если 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}

replace(map, key, value)Source

@spec replace(map(), key(), value()) :: map()

Устанавливает значение под key только если key уже существует в map.

Примеры

iex> Map.replace(%{a: 1, b: 2}, :a, 3)
%{a: 3, b: 2}

iex> Map.replace(%{a: 1}, :b, 2)
%{a: 1}

split(map, keys)Source

@spec 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)Source

@spec 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)Source

@spec 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, fun)Source

@spec update!(map(), key(), (existing_value :: value() -> new_value :: value())) ::
  map()

Обновляет key с помощью заданной функции.

Если key присутствует в map, то существующее значение передаётся в fun, и результат используется в качестве обновлённого значения 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}

update(map, key, default, fun)Source

@spec update(
  map(),
  key(),
  default :: value(),
  (existing_value :: value() -> new_value :: value())
) ::
  map()

Обновляет key в map с помощью заданной функции.

Если key присутствует в map, то существующее значение передаётся в fun, и результат используется в качестве обновлённого значения key. Если key не присутствует в map, default вставляется в качестве значения key. Значение по умолчанию не будет передаваться в функцию обновления.

Примеры

iex> Map.update(%{a: 1}, :a, 13, fn existing_value -> existing_value * 2 end)
%{a: 2}
iex> Map.update(%{a: 1}, :b, 11, fn existing_value -> existing_value * 2 end)
%{a: 1, b: 11}

values(map)Source

@spec 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.13.4/Map.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API