Spec-Zone.ru › Elixir 1.17

Источник Enum

Функции для работы со коллекциями (известными как перечисляемые).

В Elixir, перечисляемым является любой тип данных, который реализует протокол Enumerable. Listы ([1, 2, 3]), Mapы (%{foo: 1, bar: 2}) и Rangeы (1..3) являются распространёнными типами данных, используемыми как перечисляемые:

iex> Enum.map([1, 2, 3], fn x -> x * 2 end)
[2, 4, 6]

iex> Enum.sum([1, 2, 3])
6

iex> Enum.map(1..3, fn x -> x * 2 end)
[2, 4, 6]

iex> Enum.sum(1..3)
6

iex> map = %{"a" => 1, "b" => 2}
iex> Enum.map(map, fn {k, v} -> {k, v * 2} end)
[{"a", 2}, {"b", 4}]

Существуют и другие перечисляемые в языке, такие как MapSetы и тип данных, возвращаемый File.stream!/3, который позволяет просматривать файл, как если бы он был перечисляемым.

Для общего обзора всех функций в модуле Enum, см. Enum шпаргалку.

Функции в этом модуле работают за линейное время. Это означает, что время, необходимое для выполнения операции, растёт с той же скоростью, что и длина перечисляемого. Это ожидается для операций, таких как Enum.map/2. В конце концов, если мы хотим пройтись по каждому элементу в списке, то чем длиннее список, тем больше элементов нам нужно пройти, и тем дольше это займёт.

Такое линейное поведение также ожидается для операций, таких как count/1, member?/2, at/2 и аналогичных. Хотя Elixir позволяет типам данных предоставлять эффективные варианты для таких операций, вы не должны ожидать, что это всегда будет доступно, так как модуль Enum предназначен для работы с большим разнообразием типов данных, и не все типы данных могут предоставить оптимизированное поведение.

Наконец, обратите внимание, что функции в модуле Enum являются жадными: они пройдут по перечисляемому сразу же после вызова. Это особенно опасно при работе с бесконечными перечисляемыми. В таких случаях вы должны использовать модуль Stream, который позволяет лениво выражать вычисления, не проходя по коллекциям, и работать с потенциально бесконечными коллекциями. См. модуль Stream для примеров и документации.

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

Типы

acc()
default()
element()
index()

Индекс, начинающийся с нуля. Также может быть отрицательным целым числом.

t()

Функции

all?(enumerable)

Возвращает true, если все элементы в перечисляемом объекте истинны.

all?(enumerable, fun)

Возвращает true если fun истинно для всех элементов в перечисляемом объекте.

any?(enumerable)

Возвращает true если хотя бы один элемент в перечисляемом объекте истинен.

any?(enumerable, fun)

Возвращает true если fun истинно для хотя бы одного элемента в перечисляемом объекте.

at(enumerable, index, default \\ nil)

Находит элемент по заданному индексу (нумерация с нуля).

chunk_by(enumerable, fun)

Разбивает перечисляемый объект на группы по каждому элементу, для которого fun возвращает новое значение.

chunk_every(enumerable, count)

Сокращение для chunk_by/2.

chunk_every(enumerable, count, step, leftover \\ [])

Возвращает список списков, содержащих по count элементов каждый, где каждый новый фрагмент начинается с step элементов в перечисляемом объекте.

chunk_while(enumerable, acc, chunk_fun, after_fun)

Разбивает перечисляемый объект на фрагменты с точным управлением, когда каждый фрагмент генерируется.

concat(enumerables)

Принимая на вход перечисляемый объект перечисляемых объектов, конкатенирует перечисляемые в один список.

concat(left, right)

Конкатенирует перечисляемый объект слева с перечисляемым объектом справа.

count(enumerable)

Возвращает размер перечисляемого объекта.

count(enumerable, fun)

Возвращает количество элементов в перечисляемом объекте, для которых fun возвращает истинное значение.

count_until(enumerable, limit)

Подсчитывает элементы перечисляемого объекта, останавливаясь на лимите.

count_until(enumerable, fun, limit)

Подсчитывает элементы в перечисляемом объекте, для которых fun возвращает истинное значение, останавливаясь на лимите.

dedup(enumerable)

Перечисляет перечисляемый объект, возвращая список, где все последовательные повторяющиеся элементы сводятся к одному элементу.

dedup_by(enumerable, fun)

Перечисляет перечисляемый объект, возвращая список, где все последовательные повторяющиеся элементы сводятся к одному элементу.

drop(enumerable, amount)

Опускает amount элементов из перечисляемого объекта.

drop_every(enumerable, nth)

Возвращает список каждого nth элемента в перечисляемом объекте, пропуская, начиная с первого элемента.

END_OF_DOCUMENT_MARKER
drop_while(enumerable, fun)

Удаляет элементы в начале enumerable пока fun возвращает истинное значение.

each(enumerable, fun)

Вызывает заданную fun для каждого элемента в enumerable.

empty?(enumerable)

Определяет, является ли enumerable пустым.

fetch(enumerable, index)

Находит элемент по заданному index (нумерация с нуля).

fetch!(enumerable, index)

Находит элемент по заданному index (нумерация с нуля).

filter(enumerable, fun)

Фильтрует enumerable, т.е. возвращает только те элементы, для которых fun возвращает истинное значение.

find(enumerable, default \\ nil, fun)

Возвращает первый элемент, для которого fun возвращает истинное значение. Если такой элемент не найден, возвращает default.

find_index(enumerable, fun)

Аналогично find/3, но возвращает индекс (нумерация с нуля) элемента вместо самого элемента.

find_value(enumerable, default \\ nil, fun)

Аналогично find/3, но возвращает значение вызова функции вместо самого элемента.

flat_map(enumerable, fun)

Применяет данную fun к enumerable и сглаживает результат.

flat_map_reduce(enumerable, acc, fun)

Применяет отображение и сворачивание к enumerable, сглаживая полученные результаты (только на один уровень).

frequencies(enumerable)

Возвращает карту с ключами как уникальными элементами enumerable и значениями как количество каждого элемента.

frequencies_by(enumerable, key_fun)

Возвращает карту с ключами как уникальными элементами, заданными key_fun и значениями как количество каждого элемента.

group_by(enumerable, key_fun, value_fun \\ fn x -> x end)

Разбивает enumerable на группы на основе key_fun.

intersperse(enumerable, separator)

Вставляет separator между каждым элементом перечисления.

into(enumerable, collectable)

Вставляет данное enumerable в collectable.

into(enumerable, collectable, transform)

Вставляет данное enumerable в collectable согласно функции преобразования.

join(enumerable, joiner \\ "")

Объединяет данное enumerable в строку, используя joiner в качестве разделителя.

map(enumerable, fun)

Возвращает список, где каждый элемент является результатом вызова fun для каждого соответствующего элемента enumerable.

map_every(enumerable, nth, fun)

Возвращает список результатов вызова fun для каждого элемента nth в enumerable, начиная с первого.

map_intersperse(enumerable, separator, mapper)

Преобразует и вставляет разделители в перечисляемый объект за один проход.

map_join(enumerable, joiner \\ "", mapper)

Преобразует и объединяет данный enumerable за один проход.

map_reduce(enumerable, acc, fun)

Вызывает заданную функцию для каждого элемента в enumerable для его сокращения до одного элемента, сохраняя накопитель.

max(enumerable, sorter \\ &>=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)

Возвращает максимальный элемент в enumerable в соответствии с порядком терминов Erlang.

max_by(enumerable, fun, sorter \\ &>=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)

Возвращает максимальный элемент в enumerable, рассчитанный с помощью данной fun.

member?(enumerable, element)

Проверяет, существует ли element в enumerable.

min(enumerable, sorter \\ &<=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)

Возвращает минимальный элемент в enumerable в соответствии с порядком терминов Erlang.

min_by(enumerable, fun, sorter \\ &<=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)

Возвращает минимальный элемент в enumerable, рассчитанный с помощью данной fun.

min_max(enumerable, empty_fallback \\ fn -> raise Enum.EmptyError end)

Возвращает кортеж с минимальным и максимальным элементами в перечисляемом объекте в соответствии с порядком терминов Erlang.

min_max_by(enumerable, fun, sorter_or_empty_fallback \\ &</2, empty_fallback \\ fn -> raise Enum.EmptyError end)

Возвращает кортеж с минимальным и максимальным элементами в перечисляемом объекте, рассчитанными с помощью заданной функции.

product(enumerable)

Возвращает произведение всех элементов.

random(enumerable)

Возвращает случайный элемент из enumerable.

reduce(enumerable, fun)

Вызывает fun для каждого элемента в enumerable с накопителем.

reduce(enumerable, acc, fun)

Вызывает fun для каждого элемента в enumerable с накопителем.

reduce_while(enumerable, acc, fun)

Сокращает enumerable до тех пор, пока fun не вернёт {:halt, term}.

reject(enumerable, fun)

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

reverse(enumerable)

Возвращает список элементов в enumerable в обратном порядке.

END_OF_DOCUMENT_MARKER
reverse(enumerable, tail)

Обращает порядок элементов в enumerable, добавляет tail, и возвращает результат в виде списка.

reverse_slice(enumerable, start_index, count)

Обращает порядок элементов в enumerable в диапазоне от начального start_index до count элементов.

scan(enumerable, fun)

Применяет заданную функцию к каждому элементу в enumerable, сохраняя результат в списке и передавая его как накопитель для следующего вычисления. Использует первый элемент в enumerable в качестве начального значения.

scan(enumerable, acc, fun)

Применяет заданную функцию к каждому элементу в enumerable, сохраняя результат в списке и передавая его как накопитель для следующего вычисления. Использует заданное acc в качестве начального значения.

shuffle(enumerable)

Возвращает список с перетасованными элементами из enumerable.

slice(enumerable, index_range)

Возвращает подмножество списка заданного enumerable с помощью index_range.

slice(enumerable, start_index, amount)

Возвращает подмножество списка заданного enumerable, начиная с start_index (нумерация с нуля) с amount количеством элементов, если доступно.

slide(enumerable, range_or_single_index, insertion_index)

Сдвигает один или несколько элементов, заданных range_or_single_index, от enumerable к insertion_index.

sort(enumerable)

Сортирует enumerable в соответствии с порядком Erlang.

sort(enumerable, sorter)

Сортирует enumerable с помощью заданной функции.

sort_by(enumerable, mapper, sorter \\ :asc)

Сортирует отображенные результаты из enumerable в соответствии с предоставленной функцией sorter.

split(enumerable, count)

Разделяет enumerable на два перечисляемых объекта, оставляя count элементов в первом.

split_while(enumerable, fun)

Разделяет перечисляемый объект на две части в позиции элемента, для которого fun возвращает ложное значение (false или nil) в первый раз.

split_with(enumerable, fun)

Разделяет enumerable на два списка в соответствии с заданной функцией fun.

sum(enumerable)

Возвращает сумму всех элементов.

take(enumerable, amount)

Извлекает amount элементов с начала или конца enumerable.

take_every(enumerable, nth)

Возвращает список каждого nth элемента в enumerable, начиная с первого элемента.

take_random(enumerable, count)

Извлекает count случайных элементов из enumerable.

END_OF_DOCUMENT_MARKER
take_while(enumerable, fun)

Возвращает элементы из начала enumerable, пока fun возвращает истинное значение.

to_list(enumerable)

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

uniq(enumerable)

Перечисляет enumerable, удаляя все дублируемые элементы.

uniq_by(enumerable, fun)

Перечисляет enumerable, удаляя элементы, для которых функция fun вернула дублируемые элементы.

unzip(list)

Обратная функция к zip/2. Извлекает кортежи из двух элементов из заданного enumerable и группирует их вместе.

with_index(enumerable, fun_or_offset \\ 0)

Возвращает enumerable с каждым элементом, заключённым в кортеж вместе с его индексом или согласно заданной функции.

zip(enumerables)

Комбинирует соответствующие элементы из конечной коллекции перечислимых объектов в список кортежей.

zip(enumerable1, enumerable2)

Комбинирует соответствующие элементы из двух перечислимых объектов в список кортежей.

zip_reduce(enums, acc, reducer)

Редуцирует по всем заданным перечислимым объектам, останавливаясь, как только какой-либо перечислимый объект становится пустым.

zip_reduce(left, right, acc, reducer)

Редуцирует по двум перечислимым объектам, останавливаясь, как только один из них становится пустым.

zip_with(enumerables, zip_fun)

Комбинирует соответствующие элементы из конечной коллекции перечислимых объектов в список, преобразуя их с помощью функции zip_fun по мере обработки.

zip_with(enumerable1, enumerable2, zip_fun)

Комбинирует соответствующие элементы из двух перечислимых объектов в список, преобразуя их с помощью функции zip_fun по мере обработки.

Типы

acc()Source

@type acc() :: any()

default()Source

@type default() :: any()

element()Source

@type element() :: any()

index()Source

@type index() :: integer()

Индекс, начинающийся с нуля. Также может быть отрицательным целым числом.

t()Source

@type t() :: Enumerable.t()
END_OF_DOCUMENT_MARKER

Функции

all?(enumerable)Source

@spec all?(t()) :: boolean()

Возвращает истину, если все элементы в перечислимом объекте истинны.

Когда элемент имеет ложное значение (ложь или `nil`) итерация останавливается немедленно и возвращается ложь. Во всех остальных случаях возвращается истина.

Примеры

iex> Enum.all?([1, 2, 3])
true

iex> Enum.all?([1, nil, 3])
false

iex> Enum.all?([])
true

all?(enumerable, fun)Source

@spec all?(t(), (element() -> as_boolean(term()))) :: boolean()

Возвращает истину, если функция истинна для всех элементов в перечислимом объекте.

Итерируется по перечислимому объекту и вызывает функцию для каждого элемента. Если функция когда-либо возвращает ложное значение (ложь или `nil`), итерация останавливается немедленно и возвращается ложь. В противном случае возвращается истина.

Примеры

iex> Enum.all?([2, 4, 6], fn x -> rem(x, 2) == 0 end)
true

iex> Enum.all?([2, 3, 4], fn x -> rem(x, 2) == 0 end)
false

iex> Enum.all?([], fn _ -> nil end)
true

Как показывает последний пример, `all?/2` возвращает истину, если перечислимый объект пуст, независимо от функции. В пустом перечислимом объекте нет элемента, для которого функция вернёт ложное значение, поэтому результат должен быть истиной. Это хорошо определённый логический аргумент для пустых коллекций.

any?(enumerable)Source

@spec any?(t()) :: boolean()

Возвращает истину, если хотя бы один элемент в перечислимом объекте истинен.

Когда элемент имеет истинное значение (ни ложь, ни `nil`) итерация останавливается немедленно и возвращается истина. Во всех остальных случаях возвращается ложь.

Примеры

iex> Enum.any?([false, false, false])
false

iex> Enum.any?([false, true, false])
true

iex> Enum.any?([])
false

any?(enumerable, fun)Source

@spec any?(t(), (element() -> as_boolean(term()))) :: boolean()

Возвращает истину, если функция истинна хотя бы для одного элемента в перечислимом объекте.

Итерируется по перечислимому объекту и вызывает функцию для каждого элемента. Когда вызов функции возвращает истинное значение (ни ложь, ни `nil`) итерация останавливается немедленно и возвращается истина. Во всех остальных случаях возвращается ложь.

Примеры

iex> Enum.any?([2, 4, 6], fn x -> rem(x, 2) == 1 end)
false

iex> Enum.any?([2, 3, 4], fn x -> rem(x, 2) == 1 end)
true

iex> Enum.any?([], fn x -> x > 0 end)
false

at(enumerable, index, default \\ nil)Source

@spec at(t(), index(), default()) :: element() | default()

Находит элемент по заданному индексу (нумерация с нуля).

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

Можно передать отрицательный индекс, что означает, что перечисление проходит один раз, а индекс подсчитывается с конца (например, `at/3` находит последний элемент).

Примеры

iex> Enum.at([2, 4, 6], 0)
2

iex> Enum.at([2, 4, 6], 2)
6

iex> Enum.at([2, 4, 6], 4)
nil

iex> Enum.at([2, 4, 6], 4, :none)
:none

chunk_by(enumerable, fun)Source

@spec chunk_by(t(), (element() -> any())) :: [list()]

Разбивает перечислимый объект на фрагменты по каждому элементу, для которого функция возвращает новое значение.

Возвращает список списков.

Примеры

iex> Enum.chunk_by([1, 2, 2, 3, 4, 4, 6, 7, 7], &(rem(&1, 2) == 1))
[[1], [2, 2], [3], [4, 4, 6], [7, 7]]

chunk_every(enumerable, count)Source

@spec chunk_every(t(), pos_integer()) :: [list()]

Сокращение для `chunk_every/4`.

END_OF_DOCUMENT_MARKER

chunk_every(enumerable, count, step, leftover \\ [])Source

@spec chunk_every(t(), pos_integer(), pos_integer(), t() | :discard) :: [list()]

Возвращает список списков, содержащих по указанному количеству элементов каждый, где каждый новый фрагмент начинается через указанное количество элементов в перечислимом объекте.

`leftover` является необязательным и, если не указано, по умолчанию равно `[]`, т.е. фрагменты не перекрываются. Разбиение на фрагменты прекращается, как только коллекция закончится или когда будет выведен неполный фрагмент.

Если последний фрагмент не содержит необходимого количества элементов для заполнения фрагмента, элементы берутся из `leftover` для заполнения фрагмента. Если `leftover` не содержит достаточно элементов для заполнения фрагмента, то возвращается частичный фрагмент с менее чем требуемым количеством элементов.

Если `leftover` указано в функции, последний фрагмент отбрасывается, если только он не содержит ровно необходимого количества элементов.

Примеры

iex> Enum.chunk_every([1, 2, 3, 4, 5, 6], 2)
[[1, 2], [3, 4], [5, 6]]

iex> Enum.chunk_every([1, 2, 3, 4, 5, 6], 3, 2, :discard)
[[1, 2, 3], [3, 4, 5]]

iex> Enum.chunk_every([1, 2, 3, 4, 5, 6], 3, 2, [7])
[[1, 2, 3], [3, 4, 5], [5, 6, 7]]

iex> Enum.chunk_every([1, 2, 3, 4], 3, 3, [])
[[1, 2, 3], [4]]

iex> Enum.chunk_every([1, 2, 3, 4], 10)
[[1, 2, 3, 4]]

iex> Enum.chunk_every([1, 2, 3, 4, 5], 2, 3, [])
[[1, 2], [4, 5]]

iex> Enum.chunk_every([1, 2, 3, 4], 3, 3, Stream.cycle([0]))
[[1, 2, 3], [4, 0, 0]]

chunk_while(enumerable, acc, chunk_fun, after_fun)Source

@spec chunk_while(
  t(),
  acc(),
  (element(), acc() -> {:cont, chunk, acc()} | {:cont, acc()} | {:halt, acc()}),
  (acc() -> {:cont, chunk, acc()} | {:cont, acc()})
) :: Enumerable.t()
when chunk: any()

Разбивает перечислимый объект с точным управлением, когда каждый фрагмент выдаётся.

`chunk_fun` получает текущий элемент и накопитель и должен вернуть:

  • `{:cont, new_acc}` для вывода фрагмента и продолжения с накопителем
  • `{:skip, new_acc}` для не вывода фрагмента и продолжения с накопителем
  • `{:halt, new_acc}` для остановки разбиения по перечислимому объекту.

`after_fun` вызывается с конечным накопителем при завершении итерации (или `{:halt, acc}`), чтобы обработать любые оставшиеся элементы, которые были возвращены как часть накопителя, но не были выведены в качестве фрагмента функцией `chunk_fun`. Она должна вернуть:

  • `{:cont, new_acc}` для вывода фрагмента. Фрагмент будет добавлен к списку уже выведенных фрагментов.
  • `{:skip, new_acc}` для не вывода фрагмента

Накопитель (`acc`) в `chunk_while/4` необходим для отражения формата кортежа из `enumerable`, но будет отброшен, так как обход завершен.

Возвращает список выведенных фрагментов.

Примеры

iex> chunk_fun = fn element, acc ->
...>   if rem(element, 2) == 0 do
...>     {:cont, Enum.reverse([element | acc]), []}
...>   else
...>     {:cont, [element | acc]}
...>   end
...> end
iex> after_fun = fn
...>   [] -> {:cont, []}
...>   acc -> {:cont, Enum.reverse(acc), []}
...> end
iex> Enum.chunk_while(1..10, [], chunk_fun, after_fun)
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
iex> Enum.chunk_while([1, 2, 3, 5, 7], [], chunk_fun, after_fun)
[[1, 2], [3, 5, 7]]

concat(enumerables)Source

@spec concat(t()) :: t()

Принимая перечислимый список перечислимых объектов, конкатенирует их в один список.

Примеры

iex> Enum.concat([1..3, 4..6, 7..9])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

iex> Enum.concat([[1, [2], 3], [4], [5, 6]])
[1, [2], 3, 4, 5, 6]

concat(left, right)Source

@spec concat(t(), t()) :: t()

Конкатенирует перечислимый объект слева с перечислимым объектом справа.

Эта функция производит тот же результат, что и оператор `++/2` для списков.

Примеры

iex> Enum.concat(1..3, 4..6)
[1, 2, 3, 4, 5, 6]

iex> Enum.concat([1, 2, 3], [4, 5, 6])
[1, 2, 3, 4, 5, 6]

count(enumerable)Source

@spec count(t()) :: non_neg_integer()

Возвращает размер перечислимого объекта.

Примеры

iex> Enum.count([1, 2, 3])
3

count(enumerable, fun)Source

@spec count(t(), (element() -> as_boolean(term()))) :: non_neg_integer()

Возвращает количество элементов в перечислимом объекте, для которых функция возвращает истинное значение.

Примеры

iex> Enum.count([1, 2, 3, 4, 5], fn x -> rem(x, 2) == 0 end)
2

count_until(enumerable, limit)Source

@spec count_until(t(), pos_integer()) :: non_neg_integer()

Считает перечислимый объект, останавливаясь на пределе.

Это полезно для проверки определённых свойств счётчика перечислимого объекта, не пересчитывая весь перечислимый объект. Например, если требуется проверить, что счётчик равен, больше или меньше определённого значения.

Если перечислимый объект реализует Enumerable.count/1, перечислимый объект не обходится, и мы возвращаем меньшее из двух чисел. Чтобы принудительно выполнить перебор, используйте count_until/3 со значением fn _ -> true end в качестве второго аргумента.

Примеры

iex> Enum.count_until(1..20, 5)
5
iex> Enum.count_until(1..20, 50)
20
iex> Enum.count_until(1..10, 10) == 10 # At least 10
true
iex> Enum.count_until(1..11, 10 + 1) > 10 # More than 10
true
iex> Enum.count_until(1..5, 10) < 10 # Less than 10
true
iex> Enum.count_until(1..10, 10 + 1) == 10 # Exactly ten
true

count_until(enumerable, fun, limit)Source

@spec count_until(t(), (element() -> as_boolean(term())), pos_integer()) ::
  non_neg_integer()

Считает элементы в перечислимом объекте, для которых функция возвращает истинное значение, останавливаясь на пределе.

См. count/2 и count_until/2 для получения дополнительной информации.

Примеры

iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 7)
7
iex> Enum.count_until(1..20, fn x -> rem(x, 2) == 0 end, 11)
10

dedup(enumerable)Source

@spec dedup(t()) :: list()

Перечисляет перечислимый объект, возвращая список, в котором все последовательные дубликаты элементов сводятся к одному элементу.

Элементы сравниваются с помощью ===/2.

Если требуется удалить все дубликаты элементов независимо от порядка, см. uniq/1.

Примеры

iex> Enum.dedup([1, 2, 3, 3, 2, 1])
[1, 2, 3, 2, 1]

iex> Enum.dedup([1, 1, 2, 2.0, :three, :three])
[1, 2, 2.0, :three]

dedup_by(enumerable, fun)Source

@spec dedup_by(t(), (element() -> term())) :: list()

Перечисляет перечислимый объект, возвращая список, где все последовательные дубликаты элементов сводятся к одному элементу.

Функция отображает каждый элемент в терм, который используется для определения того, являются ли два элемента дубликатами.

Примеры

iex> Enum.dedup_by([{1, :a}, {2, :b}, {2, :c}, {1, :a}], fn {x, _} -> x end)
[{1, :a}, {2, :b}, {1, :a}]

iex> Enum.dedup_by([5, 1, 2, 3, 2, 1], fn x -> x > 2 end)
[5, 1, 3, 2]

drop(enumerable, amount)Source

@spec drop(t(), integer()) :: list()

Опускает заданное количество элементов из перечислимого объекта.

Если задано отрицательное количество, будут опушены последние значения. Перечислимый объект будет перечислен один раз, чтобы получить правильный индекс, и оставшиеся вычисления выполняются с конца.

Примеры

iex> Enum.drop([1, 2, 3], 2)
[3]

iex> Enum.drop([1, 2, 3], 10)
[]

iex> Enum.drop([1, 2, 3], 0)
[1, 2, 3]

iex> Enum.drop([1, 2, 3], -1)
[1, 2]

drop_every(enumerable, nth)Source

@spec drop_every(t(), non_neg_integer()) :: list()

Возвращает список каждого n-го элемента в перечислимом объекте, опуская, начиная с первого элемента.

Первый элемент всегда опускается, если n не равно 0.

Второй аргумент, определяющий каждый n-ый элемент, должен быть неотрицательным целым числом.

Примеры

iex> Enum.drop_every(1..10, 2)
[2, 4, 6, 8, 10]

iex> Enum.drop_every(1..10, 0)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

iex> Enum.drop_every([1, 2, 3], 1)
[]

drop_while(enumerable, fun)Source

@spec drop_while(t(), (element() -> as_boolean(term()))) :: list()

Опускает элементы в начале перечислимого объекта, пока функция возвращает истинное значение.

Примеры

iex> Enum.drop_while([1, 2, 3, 2, 1], fn x -> x < 3 end)
[3, 2, 1]

each(enumerable, fun)Source

@spec each(t(), (element() -> any())) :: :ok

Вызывает заданную функцию для каждого элемента в перечислимом объекте.

Возвращает перечислимый объект.

Примеры

Enum.each(["some", "example"], fn x -> IO.puts(x) end)
"some"
"example"
#=> :ok

empty?(enumerable)Source

@spec empty?(t()) :: boolean()

Определяет, является ли перечислимый объект пустым.

Возвращает `true`, если перечислимый объект пуст, иначе `false`.

Примеры

iex> Enum.empty?([])
true

iex> Enum.empty?([1, 2, 3])
false

fetch(enumerable, index)Source

@spec fetch(t(), index()) :: {:ok, element()} | :error

Находит элемент по заданному индексу (нумерация с нуля).

Возвращает найденный элемент, иначе `nil`.

Можно передать отрицательный индекс, что означает, что перечислимый объект перечисляется один раз, а индекс считается с конца (например, `-1` извлекает последний элемент).

Примеры

iex> Enum.fetch([2, 4, 6], 0)
{:ok, 2}

iex> Enum.fetch([2, 4, 6], -3)
{:ok, 2}

iex> Enum.fetch([2, 4, 6], 2)
{:ok, 6}

iex> Enum.fetch([2, 4, 6], 4)
:error

fetch!(enumerable, index)Source

@spec fetch!(t(), index()) :: element()

Находит элемент по заданному индексу (нумерация с нуля).

Вызывает исключение `{:error, :index}` если заданный индекс находится вне диапазона перечислимого объекта.

Примеры

iex> Enum.fetch!([2, 4, 6], 0)
2

iex> Enum.fetch!([2, 4, 6], 2)
6

iex> Enum.fetch!([2, 4, 6], 4)
** (Enum.OutOfBoundsError) out of bounds error

filter(enumerable, fun)Source

@spec filter(t(), (element() -> as_boolean(term()))) :: list()

Фильтрует перечислимый объект, т. е. возвращает только те элементы, для которых функция возвращает истинное значение.

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

Примеры

iex> Enum.filter([1, 2, 3], fn x -> rem(x, 2) == 0 end)
[2]
iex> Enum.filter(["apple", "pear", "banana"], fn fruit -> String.contains?(fruit, "a") end)
["apple", "pear", "banana"]
iex> Enum.filter([4, 21, 24, 904], fn seconds -> seconds > 1000 end)
[]

Обратите внимание, что `filter/2` не может фильтровать и преобразовывать элемент одновременно. Если вы хотите сделать это, рассмотрите использование flat_map/2. Например, если вы хотите преобразовать все строки, представляющие целое число, и отбросить недопустимые в одном проходе:

strings = ["1234", "abc", "12ab"]

Enum.flat_map(strings, fn string ->
  case Integer.parse(string) do
    # transform to integer
    {int, _rest} -> [int]
    # skip the value
    :error -> []
  end
end)

find(enumerable, default \\ nil, fun)Source

@spec find(t(), default(), (element() -> any())) :: element() | default()

Возвращает первый элемент, для которого функция возвращает истинное значение. Если такого элемента нет, возвращает значение по умолчанию.

Примеры

iex> Enum.find([2, 3, 4], fn x -> rem(x, 2) == 1 end)
3

iex> Enum.find([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil
iex> Enum.find([2, 4, 6], 0, fn x -> rem(x, 2) == 1 end)
0

find_index(enumerable, fun)Source

@spec find_index(t(), (element() -> any())) :: non_neg_integer() | nil

Аналогично find/3, но возвращает индекс (нумерация с нуля) элемента вместо самого элемента.

Примеры

iex> Enum.find_index([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

iex> Enum.find_index([2, 3, 4], fn x -> rem(x, 2) == 1 end)
1

find_value(enumerable, default \\ nil, fun)Source

@spec find_value(t(), default(), (element() -> found_value)) ::
  found_value | default()
when found_value: term()

Аналогично find/3, но возвращает значение вызова функции вместо самого элемента.

Значение считается найденным, когда результат имеет истинное значение (ни `nil`, ни `false`).

Примеры

iex> Enum.find_value([2, 3, 4], fn x ->
...>   if x > 2, do: x * x
...> end)
9

iex> Enum.find_value([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

iex> Enum.find_value([2, 3, 4], fn x -> rem(x, 2) == 1 end)
true

iex> Enum.find_value([1, 2, 3], "no bools!", &is_boolean/1)
"no bools!"

flat_map(enumerable, fun)Source

@spec flat_map(t(), (element() -> t())) :: list()

Применяет данную функцию к каждому элементу перечислимого объекта и уплощает результат.

Эта функция возвращает новую перечислимую последовательность, созданную путём добавления результата вызова функции для каждого элемента; концептуально, это аналогично сочетанию map/2 и concat/1.

Примеры

iex> Enum.flat_map([:a, :b, :c], fn x -> [x, x] end)
[:a, :a, :b, :b, :c, :c]

iex> Enum.flat_map([{1, 3}, {4, 6}], fn {x, y} -> x..y end)
[1, 2, 3, 4, 5, 6]

iex> Enum.flat_map([:a, :b, :c], fn x -> [[x]] end)
[[:a], [:b], [:c]]

flat_map_reduce(enumerable, acc, fun)Source

@spec flat_map_reduce(t(), acc(), fun) :: {[any()], acc()}
when fun: (element(), acc() -> {t(), acc()} | {:halt, acc()})

Применяет отображение и редукцию к перечислимому объекту, уплощая полученные результаты (только на один уровень).

Ожидается аккумулятор и функция, которая получает каждый элемент перечислимой последовательности и должна возвращать кортеж, содержащий новую перечислимую последовательность (часто список) с новым аккумулятором или кортеж с новым значением в качестве первого элемента и аккумулятором во втором.

Примеры

iex> enumerable = 1..100
iex> n = 3
iex> Enum.flat_map_reduce(enumerable, 0, fn x, acc ->
...>   if acc < n, do: {[x], acc + 1}, else: {:halt, acc}
...> end)
{[1, 2, 3], 3}

iex> Enum.flat_map_reduce(1..5, 0, fn x, acc -> {[[x]], acc + x} end)
{[[1], [2], [3], [4], [5]], 15}

frequencies(enumerable)Source

@spec frequencies(t()) :: map()

Возвращает карту с ключами как уникальными элементами перечислимого объекта и значениями как количество каждого элемента.

Примеры

iex> Enum.frequencies(~w{ant buffalo ant ant buffalo dingo})
%{"ant" => 3, "buffalo" => 2, "dingo" => 1}

frequencies_by(enumerable, key_fun)Source

@spec frequencies_by(t(), (element() -> any())) :: map()

Возвращает карту с ключами как уникальными элементами, полученными с помощью указанной функции, и значениями как количество каждого элемента.

Примеры

iex> Enum.frequencies_by(~w{aa aA bb cc}, &String.downcase/1)
%{"aa" => 2, "bb" => 1, "cc" => 1}

iex> Enum.frequencies_by(~w{aaa aA bbb cc c}, &String.length/1)
%{3 => 2, 2 => 2, 1 => 1}

group_by(enumerable, key_fun, value_fun \\ fn x -> x end)Source

@spec group_by(t(), (element() -> any()), (element() -> any())) :: map()

Разбивает перечислимый объект на группы на основе заданной функции.

Результат — это карта, где каждый ключ задаётся функцией, а каждое значение — это список элементов, заданных второй функцией. Порядок элементов в каждом списке сохраняется из исходного перечислимого объекта. Однако, как и все карты, полученная карта неупорядочена.

Примеры

iex> Enum.group_by(~w{ant buffalo cat dingo}, &String.length/1)
%{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}

iex> Enum.group_by(~w{ant buffalo cat dingo}, &String.length/1, &String.first/1)
%{3 => ["a", "c"], 5 => ["d"], 7 => ["b"]}

Ключ может быть любым значением Elixir. Например, вы можете использовать кортеж для группировки по нескольким ключам:

iex> collection = [
...>   %{id: 1, lang: "Elixir", seq: 1},
...>   %{id: 1, lang: "Java", seq: 1},
...>   %{id: 1, lang: "Ruby", seq: 2},
...>   %{id: 2, lang: "Python", seq: 1},
...>   %{id: 2, lang: "C#", seq: 2},
...>   %{id: 2, lang: "Haskell", seq: 2},
...> ]
iex> Enum.group_by(collection, &{&1.id, &1.seq})
%{
  {1, 1} => [%{id: 1, lang: "Elixir", seq: 1}, %{id: 1, lang: "Java", seq: 1}],
  {1, 2} => [%{id: 1, lang: "Ruby", seq: 2}],
  {2, 1} => [%{id: 2, lang: "Python", seq: 1}],
  {2, 2} => [%{id: 2, lang: "C#", seq: 2}, %{id: 2, lang: "Haskell", seq: 2}]
}
iex> Enum.group_by(collection, &{&1.id, &1.seq}, &{&1.id, &1.lang})
%{
  {1, 1} => [{1, "Elixir"}, {1, "Java"}],
  {1, 2} => [{1, "Ruby"}],
  {2, 1} => [{2, "Python"}],
  {2, 2} => [{2, "C#"}, {2, "Haskell"}]
}

intersperse(enumerable, separator)Source

@spec intersperse(t(), element()) :: list()

Вставляет разделитель между каждым элементом перечисления.

Примеры

iex> Enum.intersperse([1, 2, 3], 0)
[1, 0, 2, 0, 3]

iex> Enum.intersperse([1], 0)
[1]

iex> Enum.intersperse([], 0)
[]

into(enumerable, collectable)Source

@spec into(Enumerable.t(), Collectable.t()) :: Collectable.t()

Вставляет данный перечислимый объект в коллекцию.

Обратите внимание, что передача непустого списка в качестве коллекции устарела. Если вы собираете в непустой ключевой список, рассмотрите использование `Enum.into/2`. Если вы собираете в непустой список, рассмотрите что-то вроде `List.new(list) ++ enum`.

Примеры

iex> Enum.into([1, 2], [])
[1, 2]

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

iex> Enum.into(%{a: 1}, %{b: 2})
%{a: 1, b: 2}

iex> Enum.into([a: 1, a: 2], %{})
%{a: 2}

iex> Enum.into([a: 2], %{a: 1, b: 3})
%{a: 2, b: 3}

into(enumerable, collectable, transform)Source

@spec into(Enumerable.t(), Collectable.t(), (term() -> term())) :: Collectable.t()

Вставляет данный перечислимый объект в коллекцию в соответствии с функцией преобразования.

Примеры

iex> Enum.into([1, 2, 3], [], fn x -> x * 3 end)
[3, 6, 9]

iex> Enum.into(%{a: 1, b: 2}, %{c: 3}, fn {k, v} -> {k, v * 2} end)
%{a: 2, b: 4, c: 3}

join(enumerable, joiner \\ "")Source

@spec join(t(), binary()) :: binary()

Объединяет заданный перечислимый объект в строку, используя разделитель в качестве разделителя.

Если разделитель не указан, он по умолчанию равен пустой строке.

Все элементы в перечислимом объекте должны быть преобразуемы в строку или быть двоичными, иначе произойдёт ошибка.

Примеры

iex> Enum.join([1, 2, 3])
"123"

iex> Enum.join([1, 2, 3], " = ")
"1 = 2 = 3"

iex> Enum.join([["a", "b"], ["c", "d", "e", ["f", "g"]], "h", "i"], " ")
"ab cdefg h i"

map(enumerable, fun)Source

@spec map(t(), (element() -> any())) :: list()

Возвращает список, где каждый элемент является результатом вызова функции для каждого соответствующего элемента перечислимого объекта.

Для карт функция ожидает кортеж ключ-значение.

Примеры

iex> Enum.map([1, 2, 3], fn x -> x * 2 end)
[2, 4, 6]

iex> Enum.map([a: 1, b: 2], fn {k, v} -> {k, -v} end)
[a: -1, b: -2]

map_every(enumerable, nth, fun)Source

@spec map_every(t(), non_neg_integer(), (element() -> any())) :: list()

Возвращает список результатов вызова функции для каждого n-го элемента перечислимого объекта, начиная с первого элемента.

Первый элемент всегда передаётся заданной функции, если только n не равно 1.

Второй аргумент, определяющий каждый n-й элемент, должен быть целым числом, неотрицательным.

Если n равно 1, то перечислимый объект напрямую преобразуется в список без применения функции.

Примеры

iex> Enum.map_every(1..10, 2, fn x -> x + 1000 end)
[1001, 2, 1003, 4, 1005, 6, 1007, 8, 1009, 10]

iex> Enum.map_every(1..10, 3, fn x -> x + 1000 end)
[1001, 2, 3, 1004, 5, 6, 1007, 8, 9, 1010]

iex> Enum.map_every(1..5, 0, fn x -> x + 1000 end)
[1, 2, 3, 4, 5]

iex> Enum.map_every([1, 2, 3], 1, fn x -> x + 1000 end)
[1001, 1002, 1003]

map_intersperse(enumerable, separator, mapper)Source

@spec map_intersperse(t(), element(), (element() -> any())) :: list()

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

Примеры

iex> Enum.map_intersperse([1, 2, 3], :a, &(&1 * 2))
[2, :a, 4, :a, 6]

map_join(enumerable, joiner \\ "", mapper)Source

@spec map_join(t(), String.t(), (element() -> String.Chars.t())) :: String.t()

Преобразует и объединяет данный перечислимый элемент в один проход.

Если разделитель не указан, он по умолчанию равен пустой строке.

Все элементы, возвращаемые в результате вызова функции, должны быть преобразуемы в строку, в противном случае произойдёт ошибка.

Примеры

iex> Enum.map_join([1, 2, 3], &(&1 * 2))
"246"

iex> Enum.map_join([1, 2, 3], " = ", &(&1 * 2))
"2 = 4 = 6"

map_reduce(enumerable, acc, fun)Source

@spec map_reduce(t(), acc(), (element(), acc() -> {element(), acc()})) ::
  {list(), acc()}

Вызывает заданную функцию для каждого элемента в перечислимом объекте, чтобы свести его к одному элементу, сохраняя накопитель.

Возвращает кортеж, где первый элемент — это преобразованный перечислимый объект, а второй — конечный накопитель.

Функция, переданная в качестве третьего аргумента, принимает два аргумента: первый — элемент, а второй — накопитель. Функция должна возвращать кортеж с двумя элементами в формате (новый_перечислимый_объект, новый_накопитель).

Для карт первый элемент кортежа должен быть кортежем (ключ, значение).

Примеры

iex> Enum.map_reduce([1, 2, 3], 0, fn x, acc -> {x * 2, x + acc} end)
{[2, 4, 6], 6}
END_OF_DOCUMENT_MARKER

max(enumerable, sorter \\ &>=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)Source

@spec max(t(), (element(), element() -> boolean()) | module(), (-> empty_result)) ::
  element() | empty_result
when empty_result: any()

Возвращает максимальный элемент в перечислимом объекте в соответствии с порядком терминов Erlang.

По умолчанию сравнение выполняется с помощью функции сортировки `>=`/2. Если несколько элементов считаются максимальными, возвращается первый из них. Если вы хотите, чтобы возвращался последний элемент, считаемый максимальным, функция сортировки не должна возвращать true для равных элементов.

Если перечисляемый объект пуст, вызывается предоставленная функция `empty_fallback`. По умолчанию `empty_fallback` вызывает Enum.EmptyError.

Примеры

iex> Enum.max([1, 2, 3])
3

Тот факт, что эта функция использует порядок терминов Erlang, означает, что сравнение является структурным, а не семантическим. Например:

iex> Enum.max([~D[2017-03-31], ~D[2017-04-01]])
~D[2017-03-31]

В приведенном выше примере max/2 вернул 31 марта вместо 1 апреля, потому что структурное сравнение сравнивает день до года. По этой причине большинство структур предоставляют функцию "compare", такую как Date.compare/2, которая получает две структуры и возвращает `<` (меньше), `=` (равно) и `>` (больше). Если вы передадите модуль в качестве функции сортировки, Elixir автоматически будет использовать функцию `compare` данного модуля:

iex> Enum.max([~D[2017-03-31], ~D[2017-04-01]], Date)
~D[2017-04-01]

Наконец, если вы не хотите вызывать исключение при пустом перечисляемом объекте, вы можете передать значение по умолчанию для пустого объекта:

iex> Enum.max([], &>=/2, fn -> 0 end)
0

max_by(enumerable, fun, sorter \\ &>=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)Source

@spec max_by(
  t(),
  (element() -> any()),
  (element(), element() -> boolean()) | module(),
  (-> empty_result)
) :: element() | empty_result
when empty_result: any()

Возвращает максимальный элемент в перечислимом объекте в соответствии с заданной функцией `fun`.

По умолчанию сравнение выполняется с помощью функции сортировки `>=`/2. Если несколько элементов считаются максимальными, возвращается первый из них. Если вы хотите, чтобы возвращался последний элемент, считаемый максимальным, функция сортировки не должна возвращать true для равных элементов.

Вызывает предоставленную функцию `empty_fallback` и возвращает её значение, если перечисляемый объект пуст. По умолчанию `empty_fallback` вызывает Enum.EmptyError.

Примеры

iex> Enum.max_by(["a", "aa", "aaa"], fn x -> String.length(x) end)
"aaa"

iex> Enum.max_by(["a", "aa", "aaa", "b", "bbb"], &String.length/1)
"aaa"

Тот факт, что эта функция использует порядок терминов Erlang, означает, что сравнение является структурным, а не семантическим. Поэтому, если вы хотите сравнивать структуры, большинство структур предоставляют функцию "compare", такую как Date.compare/2, которая получает две структуры и возвращает `<` (меньше), `=` (равно) и `>` (больше). Если вы передадите модуль в качестве функции сортировки, Elixir автоматически будет использовать функцию `compare` данного модуля:

iex> users = [
...>   %{name: "Ellis", birthday: ~D[1943-05-11]},
...>   %{name: "Lovelace", birthday: ~D[1815-12-10]},
...>   %{name: "Turing", birthday: ~D[1912-06-23]}
...> ]
iex> Enum.max_by(users, &(&1.birthday), Date)
%{name: "Ellis", birthday: ~D[1943-05-11]}

Наконец, если вы не хотите вызывать исключение при пустом перечисляемом объекте, вы можете передать значение по умолчанию для пустого объекта:

iex> Enum.max_by([], &String.length/1, fn -> nil end)
nil

member?(enumerable, element)Source

@spec member?(t(), element()) :: boolean()

Проверяет, существует ли элемент внутри перечислимого объекта.

Членство проверяется с помощью оператора совпадения (===/2).

Примеры

iex> Enum.member?(1..10, 5)
true
iex> Enum.member?(1..10, 5.0)
false

iex> Enum.member?([1.0, 2.0, 3.0], 2)
false
iex> Enum.member?([1.0, 2.0, 3.0], 2.000)
true

iex> Enum.member?([:a, :b, :c], :d)
false

Когда вызывается вне охраняемых участков кода, операторы in и not in работают с помощью этой функции.

min(enumerable, sorter \\ &<=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)Source

@spec min(t(), (element(), element() -> boolean()) | module(), (-> empty_result)) ::
  element() | empty_result
when empty_result: any()

Возвращает минимальный элемент в перечислимом объекте в соответствии с порядком Erlang.

По умолчанию сравнение выполняется с помощью функции сортировки `<=`/2. Если несколько элементов считаются минимальными, возвращается первый найденный. Если вы хотите вернуть последний минимальный элемент, функция сортировки не должна возвращать true для равных элементов.

Если перечислимый объект пуст, вызывается предоставленная функция `empty_fallback`. По умолчанию `empty_fallback` генерирует исключение Enum.EmptyError.

Примеры

iex> Enum.min([1, 2, 3])
1

Тот факт, что эта функция использует порядок Erlang, означает, что сравнение структурное, а не семантическое. Например:

iex> Enum.min([~D[2017-03-31], ~D[2017-04-01]])
~D[2017-04-01]

В примере выше, min/2 вернула 1 апреля вместо 31 марта, потому что структурное сравнение сравнивает день до года. По этой причине большинство структур предоставляют функцию «compare», такую как Date.compare/2, которая получает две структуры и возвращает `<` (меньше), `=` (равно) и `>` (больше). Если вы передадите модуль в качестве функции сортировки, Elixir автоматически будет использовать функцию `compare` указанного модуля:

iex> Enum.min([~D[2017-03-31], ~D[2017-04-01]], Date)
~D[2017-03-31]

Наконец, если вы не хотите генерировать исключение при пустом перечислимом объекте, вы можете передать обработчик пустого объекта:

iex> Enum.min([], fn -> 0 end)
0

min_by(enumerable, fun, sorter \\ &<=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)Source

@spec min_by(
  t(),
  (element() -> any()),
  (element(), element() -> boolean()) | module(),
  (-> empty_result)
) :: element() | empty_result
when empty_result: any()

Возвращает минимальный элемент в перечислимом объекте, рассчитанный с помощью предоставленной функции.

По умолчанию сравнение выполняется с помощью функции сортировки `<=`/2. Если несколько элементов считаются минимальными, возвращается первый найденный. Если вы хотите вернуть последний минимальный элемент, функция сортировки не должна возвращать true для равных элементов.

Вызывает предоставленную функцию `empty_fallback` и возвращает её значение, если перечислимый объект пуст. По умолчанию `empty_fallback` генерирует исключение Enum.EmptyError.

Примеры

iex> Enum.min_by(["a", "aa", "aaa"], fn x -> String.length(x) end)
"a"

iex> Enum.min_by(["a", "aa", "aaa", "b", "bbb"], &String.length/1)
"a"

Тот факт, что эта функция использует порядок Erlang, означает, что сравнение структурное, а не семантическое. Поэтому, если вам нужно сравнить структуры, большинство структур предоставляют функцию «compare», такую как Date.compare/2, которая получает две структуры и возвращает `<` (меньше), `=` (равно) и `>` (больше). Если вы передадите модуль в качестве функции сортировки, Elixir автоматически будет использовать функцию `compare` указанного модуля:

iex> users = [
...>   %{name: "Ellis", birthday: ~D[1943-05-11]},
...>   %{name: "Lovelace", birthday: ~D[1815-12-10]},
...>   %{name: "Turing", birthday: ~D[1912-06-23]}
...> ]
iex> Enum.min_by(users, &(&1.birthday), Date)
%{name: "Lovelace", birthday: ~D[1815-12-10]}

Наконец, если вы не хотите генерировать исключение при пустом перечислимом объекте, вы можете передать обработчик пустого объекта:

iex> Enum.min_by([], &String.length/1, fn -> nil end)
nil

min_max(enumerable, empty_fallback \\ fn -> raise Enum.EmptyError end)Source

@spec min_max(t(), (-> empty_result)) :: {element(), element()} | empty_result
when empty_result: any()

Возвращает кортеж с минимальным и максимальным элементами в перечислимом объекте в соответствии с порядком Erlang.

Если несколько элементов считаются максимальными или минимальными, возвращается первый найденный.

Вызывает предоставленную функцию `empty_fallback` и возвращает её значение, если перечислимый объект пуст. По умолчанию `empty_fallback` генерирует исключение Enum.EmptyError.

Примеры

iex> Enum.min_max([2, 3, 1])
{1, 3}

iex> Enum.min_max([], fn -> {nil, nil} end)
{nil, nil}
END_OF_DOCUMENT_MARKER

min_max_by(enumerable, fun, sorter_or_empty_fallback \\ &</2, empty_fallback \\ fn -> raise Enum.EmptyError end)Source

@spec min_max_by(
  t(),
  (element() -> any()),
  (element(), element() -> boolean()) | module(),
  (-> empty_result)
) :: {element(), element()} | empty_result
when empty_result: any()

Возвращает кортеж с минимальным и максимальным элементами в перечислимом объекте, рассчитанными с помощью заданной функции.

Если несколько элементов считаются максимальными или минимальными, возвращается первый найденный.

Примеры

iex> Enum.min_max_by(["aaa", "bb", "c"], fn x -> String.length(x) end)
{"c", "aaa"}

iex> Enum.min_max_by(["aaa", "a", "bb", "c", "ccc"], &String.length/1)
{"a", "aaa"}

iex> Enum.min_max_by([], &String.length/1, fn -> {nil, nil} end)
{nil, nil}

Тот факт, что эта функция использует эрланговскую терминологию, означает, что сравнение является структурным, а не семантическим. Поэтому, если вы хотите сравнить структуры, большинство структур предоставляют функцию «compare», например Date.compare/2, которая получает две структуры и возвращает :lt (меньше), :eq (равно) и :gt (больше). Если вы передадите модуль как функцию сортировки, Elixir автоматически будет использовать функцию compare/2 указанного модуля:

iex> users = [
...>   %{name: "Ellis", birthday: ~D[1943-05-11]},
...>   %{name: "Lovelace", birthday: ~D[1815-12-10]},
...>   %{name: "Turing", birthday: ~D[1912-06-23]}
...> ]
iex> Enum.min_max_by(users, &(&1.birthday), Date)
{
  %{name: "Lovelace", birthday: ~D[1815-12-10]},
  %{name: "Ellis", birthday: ~D[1943-05-11]}
}

Наконец, если вы не хотите генерировать исключение при пустом перечислимом объекте, вы можете передать значение по умолчанию для пустого случая:

iex> Enum.min_max_by([], &String.length/1, fn -> nil end)
nil

product(enumerable)Source

@spec product(t()) :: number()

Возвращает произведение всех элементов.

Вызывает исключение ArithmeticError, если перечислимый объект содержит нечисловое значение.

Примеры

iex> Enum.product([])
1
iex> Enum.product([2, 3, 4])
24
iex> Enum.product([2.0, 3.0, 4.0])
24.0

random(enumerable)Source

@spec random(t()) :: element()

Возвращает случайный элемент из перечислимого объекта.

Вызывает исключение Enum.EmptyError, если перечислимый объект пуст.

Эта функция использует эрланговский модуль :rand для вычисления случайного значения. Обратитесь к его документации для установки другого алгоритма генерации случайных чисел или другого начального значения.

Если в функцию передается диапазон, эта функция выберет случайное значение в пределах этого диапазона, не перебирая весь диапазон (тем самым выполняется за постоянное время и постоянную память).

Примеры

В примерах ниже используется псевдослучайный алгоритм :exsss, поскольку он является стандартным по умолчанию с Erlang/OTP 22:

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {100, 101, 102})
iex> Enum.random([1, 2, 3])
2
iex> Enum.random([1, 2, 3])
1
iex> Enum.random(1..1_000)
309

Реализация

Случайные функции в этом модуле реализуют выборку с заданным объемом, что позволяет им выбирать из бесконечных коллекций. В частности, мы реализуем алгоритм L, как описано Ким-Хунгом Ли в «Алгоритмах выборки с заданным объемом со сложностью O(n(1+log(N/n)))».

reduce(enumerable, fun)Source

@spec reduce(t(), (element(), acc() -> acc())) :: acc()

Вызывает функцию для каждого элемента в перечислимом объекте с аккумулятором.

Вызывает исключение Enum.EmptyError, если перечислимый объект пуст.

Первый элемент перечислимого объекта используется в качестве начального значения аккумулятора. Затем функция вызывается с следующим элементом и аккумулятором. Результат, возвращенный функцией, используется в качестве аккумулятора для следующей итерации, рекурсивно. Когда перечислимый объект завершен, возвращается последний аккумулятор.

Поскольку первый элемент перечислимого объекта используется в качестве начального значения аккумулятора, функция будет выполняться только определенное количество раз, где определенное количество — длина перечислимого объекта. Эта функция не будет вызывать указанную функцию для перечислимых объектов длиной в один элемент.

Если вы хотите использовать другое значение для аккумулятора, используйте Enum.reduce/3.

Примеры

iex> Enum.reduce([1, 2, 3, 4], fn x, acc -> x * acc end)
24

reduce(enumerable, acc, fun)Source

@spec reduce(t(), acc(), (element(), acc() -> acc())) :: acc()

Вызывает функцию для каждого элемента в перечислимом объекте с накопителем.

Начальное значение накопителя — переданное значение. Функция вызывается для каждого элемента в перечислимом объекте с накопителем. Результат, возвращённый функцией, используется в качестве накопителя для следующей итерации. Функция возвращает последний накопитель.

Примеры

iex> Enum.reduce([1, 2, 3], 0, fn x, acc -> x + acc end)
6

iex> Enum.reduce(%{a: 2, b: 3, c: 4}, 0, fn {_key, val}, acc -> acc + val end)
9

Reduce как строительный блок

Reduce (иногда называемый редукцией) — это базовый строительный блок в функциональном программировании. Почти все функции в модуле Enum могут быть реализованы на основе reduce. Эти функции часто полагаются на другие операции, такие как Enum.reverse/1, которые оптимизированы в среде выполнения.

Например, мы можем реализовать map/2 в терминах reduce/3 следующим образом:

def my_map(enumerable, fun) do
  enumerable
  |> Enum.reduce([], fn x, acc -> [fun.(x) | acc] end)
  |> Enum.reverse()
end

В примере выше, Enum.reduce/3 накапливает результат каждого вызова fun в список в обратном порядке, который правильно упорядочивается в конце, вызывая Enum.reverse/1.

Реализация функций, таких как map/2, filter/2 и другие, — хорошая практика для понимания возможностей Enum.reduce/3. Когда операция не может быть выражена ни одной из функций в модуле Enum, разработчики, скорее всего, прибегнут к reduce/3.

reduce_while(enumerable, acc, fun)Source

@spec reduce_while(t(), any(), (element(), any() -> {:cont, any()} | {:halt, any()})) ::
  any()

Рекурсивно уменьшает перечислимый объект до тех пор, пока функция не вернёт false.

Возвращаемое значение для функции должно быть:

  • true для продолжения уменьшения с аккумулятором в качестве нового накопителя или
  • false для остановки уменьшения

Если функция вернёт false, уменьшение останавливается, и функция возвращает аккумулятор. В противном случае, если перечислимый объект исчерпан, функция возвращает аккумулятор последнего элемента.

Примеры

iex> Enum.reduce_while(1..100, 0, fn x, acc ->
...>   if x < 5 do
...>     {:cont, acc + x}
...>   else
...>     {:halt, acc}
...>   end
...> end)
10
iex> Enum.reduce_while(1..100, 0, fn x, acc ->
...>   if x > 0 do
...>     {:cont, acc + x}
...>   else
...>     {:halt, acc}
...>   end
...> end)
5050

reject(enumerable, fun)Source

@spec reject(t(), (element() -> as_boolean(term()))) :: list()

Возвращает список элементов в перечислимом объекте, исключая те, для которых функция возвращает true.

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

Примеры

iex> Enum.reject([1, 2, 3], fn x -> rem(x, 2) == 0 end)
[1, 3]

reverse(enumerable)Source

@spec reverse(t()) :: list()

Возвращает список элементов в перечислимом объекте в обратном порядке.

Примеры

iex> Enum.reverse([1, 2, 3])
[3, 2, 1]

reverse(enumerable, tail)Source

@spec reverse(t(), t()) :: list()

Инвертирует элементы в перечислимом объекте, добавляет хвост, и возвращает результат как список.

Это оптимизация для enumerable |> Enum.reverse() |> Enum.concat(tail).

Примеры

iex> Enum.reverse([1, 2, 3], [4, 5, 6])
[3, 2, 1, 4, 5, 6]
END_OF_DOCUMENT_MARKER

reverse_slice(enumerable, start_index, count)Source

@spec reverse_slice(t(), non_neg_integer(), non_neg_integer()) :: list()

Инвертирует элементы перечисляемого объекта в диапазоне от начального индекса до заданного количества элементов.

Если начальный индекс больше размера оставшейся части перечисляемого объекта, то эта функция инвертирует остаток перечисляемого объекта.

Примеры

iex> Enum.reverse_slice([1, 2, 3, 4, 5, 6], 2, 4)
[1, 2, 6, 5, 4, 3]

scan(enumerable, fun)Source

@spec scan(t(), (element(), any() -> any())) :: list()

Применяет данную функцию к каждому элементу в перечисляемом объекте, сохраняя результат в списке и передавая его как накопитель для следующего вычисления. Использует первый элемент в перечисляемом объекте в качестве начального значения.

Примеры

iex> Enum.scan(1..5, &(&1 + &2))
[1, 3, 6, 10, 15]

scan(enumerable, acc, fun)Source

@spec scan(t(), any(), (element(), any() -> any())) :: list()

Применяет данную функцию к каждому элементу в перечисляемом объекте, сохраняя результат в списке и передавая его как накопитель для следующего вычисления. Использует заданное значение в качестве начального значения.

Примеры

iex> Enum.scan(1..5, 0, &(&1 + &2))
[1, 3, 6, 10, 15]

shuffle(enumerable)Source

@spec shuffle(t()) :: list()

Возвращает список с элементами перечисляемого объекта перемешанными.

Эта функция использует модуль Erlang модуль `rand` для вычисления случайного значения. Проверьте его документацию для настройки другого алгоритма генерации случайных чисел или другого начального значения.

Примеры

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

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {11, 22, 33})
iex> Enum.shuffle([1, 2, 3])
[2, 1, 3]
iex> Enum.shuffle([1, 2, 3])
[2, 3, 1]

slice(enumerable, index_range)Source

@spec slice(t(), Range.t()) :: list()

Возвращает подмножество списка заданного перечисляемого объекта с помощью указанного диапазона индексов.

Диапазон индексов должен быть диапазоном. Учитывая диапазон, удаляются элементы перед начальным индексом (нумерация с 0), затем берутся элементы до конечного индекса (включительно).

Индексы нормализуются, то есть отрицательные индексы будут считаться с конца (например, -1 означает последний элемент перечисляемого объекта).

Если начальный индекс выходит за пределы, ему присваивается индекс последнего элемента.

Если нормализованный начальный индекс или конечный индекс выходит за пределы заданного перечисляемого объекта, или если конечный индекс больше начального индекса, то возвращается пустой список.

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

Примеры

iex> Enum.slice([1, 2, 3, 4, 5], 1..3)
[2, 3, 4]

iex> Enum.slice([1, 2, 3, 4, 5], 3..10)
[4, 5]

# Last three elements (negative indexes)
iex> Enum.slice([1, 2, 3, 4, 5], -3..-1)
[3, 4, 5]

Для диапазонов, где индексы убывают, вам нужно явно указать их как возрастающие:

iex> Enum.slice([1, 2, 3, 4, 5], 1..-2//1)
[2, 3, 4]

Шаг может быть любым положительным числом. Например, чтобы получить каждые 2 элемента из коллекции:

iex> Enum.slice([1, 2, 3, 4, 5], 0..-1//2)
[1, 3, 5]

Чтобы получить каждый третий элемент из первых десяти элементов:

iex> integers = Enum.to_list(1..20)
iex> Enum.slice(integers, 0..9//3)
[1, 4, 7, 10]

Если первая позиция находится после конца перечисляемого объекта или после последней позиции диапазона, возвращается пустой список:

iex> Enum.slice([1, 2, 3, 4, 5], 6..10)
[]

# first is greater than last
iex> Enum.slice([1, 2, 3, 4, 5], 6..5//1)
[]

slice(enumerable, start_index, amount)Source

@spec slice(t(), index(), non_neg_integer()) :: list()

Возвращает подмножество списка заданного перечисляемого объекта, начиная с указанного индекса (нумерация с нуля) и содержащего указанное количество элементов, если доступно.

Для заданного начального индекса, удаляются элементы перед элементом с указанным индексом, а затем берутся указанное количество элементов, возвращая столько элементов, сколько возможно, если элементов недостаточно.

Можно передать отрицательный начальный индекс, что означает, что перечисляемый объект перебирается один раз, а индекс отсчитывается с конца (например, -1 начинает срез с последнего элемента).

Возвращает пустой список, если количество элементов равно нулю или если начальный индекс находится за пределами границ.

Примеры

iex> Enum.slice(1..100, 5, 10)
[6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

# amount to take is greater than the number of elements
iex> Enum.slice(1..10, 5, 100)
[6, 7, 8, 9, 10]

iex> Enum.slice(1..10, 5, 0)
[]

# using a negative start index
iex> Enum.slice(1..10, -6, 3)
[5, 6, 7]
iex> Enum.slice(1..10, -11, 5)
[1, 2, 3, 4, 5]

# out of bound start index
iex> Enum.slice(1..10, 10, 5)
[]

slide(enumerable, range_or_single_index, insertion_index)Source

@spec slide(t(), Range.t() | index(), index()) :: list()

Сдвигает один или несколько элементов, заданных диапазоном индексов, на указанный индекс.

Семантика диапазона, подлежащего перемещению, соответствует семантике slice/2. В частности, это означает:

  • Индексы нормализуются, то есть отрицательные индексы будут отсчитываться с конца (например, -1 означает последний элемент перечисляемого объекта). Это приведет к двум прохождениям по вашему перечисляемому объекту для типов, таких как списки, которые не предоставляют постоянное время подсчёта.

  • Если нормализованный диапазон индексов выходит за пределы, диапазон усекается до последнего элемента.

  • Если нормализованный диапазон индексов выходит за пределы, выбранный диапазон для сдвига будет пустым, поэтому вы получите исходный список.

  • Убывающие диапазоны (например, `2..-1`) также выбирают пустой диапазон для перемещения, поэтому вы получите исходный список.

  • Диапазоны с любым шагом, кроме 1, вызовут ошибку.

Примеры

# Slide a single element
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], 5, 1)
[:a, :f, :b, :c, :d, :e, :g]

# Slide a range of elements backward
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], 3..5, 1)
[:a, :d, :e, :f, :b, :c, :g]

# Slide a range of elements forward
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], 1..3, 5)
[:a, :e, :f, :b, :c, :d, :g]

# Slide with negative indices (counting from the end)
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], 3..-1//1, 2)
[:a, :b, :d, :e, :f, :g, :c]
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], -4..-2, 1)
[:a, :d, :e, :f, :b, :c, :g]

# Insert at negative indices (counting from the end)
iex> Enum.slide([:a, :b, :c, :d, :e, :f, :g], 3, -1)
[:a, :b, :c, :e, :f, :g, :d]

sort(enumerable)Source

@spec sort(t()) :: list()

Сортирует перечисляемый объект в соответствии с порядком Erlang.

Эта функция использует алгоритм слияния. Не используйте эту функцию для сортировки структур, см. sort/2 для получения дополнительной информации.

Примеры

iex> Enum.sort([3, 2, 1])
[1, 2, 3]
END_OF_DOCUMENT_MARKER

sort(enumerable, sorter)Source

@spec sort(
  t(),
  (element(), element() -> boolean())
  | :asc
  | :desc
  | module()
  | {:asc | :desc, module()}
) :: list()

Сортирует перечислимый объект по заданной функции.

Эта функция использует алгоритм слияния. Переданная функция должна сравнивать два аргумента и возвращать значение, если первый аргумент предшествует второму или находится на том же месте.

Примеры

iex> Enum.sort([1, 2, 3], &(&1 >= &2))
[3, 2, 1]

Алгоритм сортировки будет стабильным, если переданная функция возвращает значение, если значения равны:

iex> Enum.sort(["some", "kind", "of", "monster"], &(byte_size(&1) <= byte_size(&2)))
["of", "some", "kind", "monster"]

Если функция не возвращает значение для равных значений, сортировка нестабильна и порядок равных элементов может быть изменён. Например:

iex> Enum.sort(["some", "kind", "of", "monster"], &(byte_size(&1) < byte_size(&2)))
["of", "kind", "some", "monster"]

Возрастание и убывание (с версии v1.10.0)

sort/2 позволяет разработчику передавать `:asc` или `:desc` в качестве сортировщика, что удобно для &<=/2 и &>=/2 соответственно.

iex> Enum.sort([2, 3, 1], :asc)
[1, 2, 3]
iex> Enum.sort([2, 3, 1], :desc)
[3, 2, 1]

Сортировка структур

Не используйте </2, <=/2, >/2, >=/2 и им подобные при сортировке структур. Это связано с тем, что встроенные операторы выше выполняют структурное сравнение, а не семантическое. Представьте, что мы сортируем следующий список дат:

iex> dates = [~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]]
iex> Enum.sort(dates)
[~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]]

Обратите внимание, что возвращаемый результат неверен, потому что sort/1 по умолчанию использует <=/2, который будет сравнивать их структуру. При сравнении структур поля сравниваются в алфавитном порядке, что означает, что даты выше будут сравниваться по `year`, `month` и затем `day`, что является обратным тому, что нам нужно.

По этой причине большинство структур предоставляют функцию "compare", например, Date.compare/2, которая получает две структуры и возвращает `меньше`, `равно` и `больше`. Если вы передаёте модуль как функцию сортировки, Elixir автоматически будет использовать функцию `compare` данного модуля:

iex> dates = [~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]]
iex> Enum.sort(dates, Date)
[~D[2019-01-01], ~D[2019-06-06], ~D[2020-03-02]]

Для получения всех дат в порядке убывания вы можете обернуть модуль в кортеж с `:desc` или `:descend` в качестве первого элемента:

iex> dates = [~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]]
iex> Enum.sort(dates, {:asc, Date})
[~D[2019-01-01], ~D[2019-06-06], ~D[2020-03-02]]
iex> dates = [~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]]
iex> Enum.sort(dates, {:desc, Date})
[~D[2020-03-02], ~D[2019-06-06], ~D[2019-01-01]]

sort_by(enumerable, mapper, sorter \\ :asc)Source

@spec sort_by(
  t(),
  (element() -> mapped_element),
  (element(), element() -> boolean())
  | :asc
  | :desc
  | module()
  | {:asc | :desc, module()}
) :: list()
when mapped_element: element()

Сортирует отображённые результаты перечислимого объекта в соответствии с предоставленной функцией отображения.

Эта функция отображает каждый элемент перечислимого объекта с помощью предоставленной функции. После этого перечисляемый объект сортируется по отображённым элементам с использованием сортировщика, который по умолчанию равен `:asc` и сортирует элементы по возрастанию.

sort_by/3 отличается от sort/2 тем, что рассчитывает значение сравнения для каждого элемента в перечисляемом объекте один раз вместо одного раза для каждого элемента в каждом сравнении. Если одна и та же функция вызывается для обоих элементов, использование sort_by/3 более эффективно.

Возрастание и убывание (с версии v1.10.0)

sort_by/3 позволяет разработчику передавать `:asc` или `:desc` в качестве сортировщика, что удобно для &<=/2 и &>=/2 соответственно:

iex> Enum.sort_by([2, 3, 1], &(&1), :asc)
[1, 2, 3]

iex> Enum.sort_by([2, 3, 1], &(&1), :desc)
[3, 2, 1]

Примеры

Использование по умолчанию `:asc`:

iex> Enum.sort_by(["some", "kind", "of", "monster"], &byte_size/1)
["of", "some", "kind", "monster"]

Сортировка по нескольким свойствам — сначала по размеру, затем по первой букве (это использует тот факт, что кортежи сравниваются элемент за элементом):

iex> Enum.sort_by(["some", "kind", "of", "monster"], &{byte_size(&1), String.first(&1)})
["of", "kind", "some", "monster"]

Аналогично sort/2, можно передать пользовательский сортировщик:

iex> Enum.sort_by(["some", "kind", "of", "monster"], &byte_size/1, :desc)
["monster", "some", "kind", "of"]

Как и в sort/2, избегайте использования функции сортировки по умолчанию для сортировки структур, так как по умолчанию она выполняет структурное сравнение вместо семантического. В таких случаях следует передать функцию сортировки в качестве третьего элемента или любой модуль, который реализует функцию `compare`. Например, чтобы отсортировать пользователей по дате рождения в порядке возрастания и убывания соответственно:

iex> users = [
...>   %{name: "Ellis", birthday: ~D[1943-05-11]},
...>   %{name: "Lovelace", birthday: ~D[1815-12-10]},
...>   %{name: "Turing", birthday: ~D[1912-06-23]}
...> ]
iex> Enum.sort_by(users, &(&1.birthday), Date)
[
  %{name: "Lovelace", birthday: ~D[1815-12-10]},
  %{name: "Turing", birthday: ~D[1912-06-23]},
  %{name: "Ellis", birthday: ~D[1943-05-11]}
]
iex> Enum.sort_by(users, &(&1.birthday), {:desc, Date})
[
  %{name: "Ellis", birthday: ~D[1943-05-11]},
  %{name: "Turing", birthday: ~D[1912-06-23]},
  %{name: "Lovelace", birthday: ~D[1815-12-10]}
]

Характеристики производительности

Как подробно описано в исходном разделе, sort_by/3 вычисляет значение сравнения для каждого элемента в перечисляемом объекте один раз вместо одного раза для каждого элемента в каждом сравнении. Это подразумевает, что sort_by/3 должен выполнить начальный проход по данным для вычисления этих значений.

Однако, если эти значения легко вычисляются, например, вы уже извлекли поле, по которому хотите отсортировать, в кортеж, то эти дополнительные проходы становятся накладными. В таких случаях следует использовать List.keysort/3.

Давайте рассмотрим пример. Представьте, у вас есть список продуктов и список идентификаторов. Вы хотите сохранить все продукты, которые находятся в заданных идентификаторах, и вернуть их названия, отсортированные по цене. Вы можете написать это так:

for(
  product <- products,
  product.id in ids,
  do: product
)
|> Enum.sort_by(& &1.price)
|> Enum.map(& &1.name)

Однако, вы также можете написать это так:

for(
  product <- products,
  product.id in ids,
  do: {product.name, product.price}
)
|> List.keysort(1)
|> Enum.map(&elem(&1, 0))

Использование List.keysort/3 станет лучшим выбором для кода, чувствительного к производительности, так как оно избегает дополнительных проходов.

split(enumerable, count)Source

@spec split(t(), integer()) :: {list(), list()}

Разделяет перечисляемый объект на два перечисляемых объекта, оставляя заданное количество элементов в первом.

Если `count` является отрицательным числом, оно начинает отсчёт с конца к началу перечислимого объекта.

Обратите внимание, что отрицательное `count` подразумевает, что `enumerable` будет перечислен дважды: один раз для расчёта позиции и второй раз для фактического разделения.

Примеры

iex> Enum.split([1, 2, 3], 2)
{[1, 2], [3]}

iex> Enum.split([1, 2, 3], 10)
{[1, 2, 3], []}

iex> Enum.split([1, 2, 3], 0)
{[], [1, 2, 3]}

iex> Enum.split([1, 2, 3], -1)
{[1, 2], [3]}

iex> Enum.split([1, 2, 3], -5)
{[], [1, 2, 3]}

split_while(enumerable, fun)Source

@spec split_while(t(), (element() -> as_boolean(term()))) :: {list(), list()}

Разделяет перечисляемый объект на две части в позиции элемента, для которого функция возвращает ложное значение (`false` или `nil`) в первый раз.

Возвращает кортеж из двух элементов со списками элементов. Элемент, вызвавший разделение, является частью второго списка.

Примеры

iex> Enum.split_while([1, 2, 3, 4], fn x -> x < 3 end)
{[1, 2], [3, 4]}

iex> Enum.split_while([1, 2, 3, 4], fn x -> x < 0 end)
{[], [1, 2, 3, 4]}

iex> Enum.split_while([1, 2, 3, 4], fn x -> x > 0 end)
{[1, 2, 3, 4], []}
END_OF_DOCUMENT_MARKER

split_with(enumerable, fun)Source

@spec split_with(t(), (element() -> as_boolean(term()))) :: {list(), list()}

Разделяет перечислимый объект на две списки в соответствии с заданной функцией.

Разделяет заданный перечислимый объект на две списки, вызывая функцию с каждым элементом в перечислимом объекте в качестве единственного аргумента. Возвращает кортеж с первой списком, содержащим все элементы в перечислимом объекте, для которых применение функции вернуло истинное значение, и второй список со всеми элементами, для которых применение функции вернуло ложное значение (или `false`, или `nil`).

Элементы в обоих возвращаемых списках находятся в том же относительном порядке, что и в исходном перечислимом объекте (если такой перечислимый объект был упорядоченным, например, список). См. примеры ниже.

Примеры

iex> Enum.split_with([5, 4, 3, 2, 1, 0], fn x -> rem(x, 2) == 0 end)
{[4, 2, 0], [5, 3, 1]}

iex> Enum.split_with([a: 1, b: -2, c: 1, d: -3], fn {_k, v} -> v < 0 end)
{[b: -2, d: -3], [a: 1, c: 1]}

iex> Enum.split_with([a: 1, b: -2, c: 1, d: -3], fn {_k, v} -> v > 50 end)
{[], [a: 1, b: -2, c: 1, d: -3]}

iex> Enum.split_with([], fn {_k, v} -> v > 50 end)
{[], []}

sum(enumerable)Source

@spec sum(t()) :: number()

Возвращает сумму всех элементов.

Вызывает исключение ArithmeticError, если перечислимый объект содержит нечисловое значение.

Примеры

iex> Enum.sum([1, 2, 3])
6

iex> Enum.sum(1..10)
55

iex> Enum.sum(1..10//2)
25

take(enumerable, amount)Source

@spec take(t(), integer()) :: list()

Берет количество элементов с начала или конца перечислимого объекта.

Если задано положительное количество, оно берет указанное количество элементов с начала перечислимого объекта.

Если задано отрицательное количество, оно берет указанное количество элементов с конца. Перечислимый объект будет перечислен один раз, чтобы получить правильный индекс, а оставшиеся вычисления выполняются с конца.

Если количество равно 0, возвращается пустой список.

Примеры

iex> Enum.take([1, 2, 3], 2)
[1, 2]

iex> Enum.take([1, 2, 3], 10)
[1, 2, 3]

iex> Enum.take([1, 2, 3], 0)
[]

iex> Enum.take([1, 2, 3], -1)
[3]

take_every(enumerable, nth)Source

@spec take_every(t(), non_neg_integer()) :: list()

Возвращает список каждого n-го элемента в перечислимом объекте, начиная с первого элемента.

Первый элемент всегда включается, если n не равно 0.

Второй аргумент, определяющий каждый n-й элемент, должен быть неотрицательным целым числом.

Примеры

iex> Enum.take_every(1..10, 2)
[1, 3, 5, 7, 9]

iex> Enum.take_every(1..10, 0)
[]

iex> Enum.take_every([1, 2, 3], 1)
[1, 2, 3]

take_random(enumerable, count)Source

@spec take_random(t(), non_neg_integer()) :: list()

Берет случайные элементы из перечислимого объекта.

Обратите внимание, что эта функция пройдёт по всему перечислимому объекту для получения случайного подсписка.

См. random/1 для примечаний об реализации и случайном зерне.

Примеры

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Enum.take_random(1..10, 2)
[6, 1]
iex> Enum.take_random(?a..?z, 5)
~c"bkzmt"

take_while(enumerable, fun)Source

@spec take_while(t(), (element() -> as_boolean(term()))) :: list()

Берет элементы с начала перечислимого объекта, пока функция возвращает истинное значение.

Примеры

iex> Enum.take_while([1, 2, 3], fn x -> x < 3 end)
[1, 2]

to_list(enumerable)Source

@spec to_list(t()) :: [element()]

Преобразует перечислимый объект в список.

Примеры

iex> Enum.to_list(1..3)
[1, 2, 3]

uniq(enumerable)Source

@spec uniq(t()) :: list()

Перечисляет перечислимый объект, удаляя все дублирующиеся элементы.

Примеры

iex> Enum.uniq([1, 2, 3, 3, 2, 1])
[1, 2, 3]

uniq_by(enumerable, fun)Source

@spec uniq_by(t(), (element() -> term())) :: list()

Перечисляет перечислимый объект, удаляя элементы, для которых функция вернула дублирующиеся элементы.

Функция сопоставляет каждый элемент с термином. Два элемента считаются дубликатами, если возвращаемое значение функции одинаково для обоих.

Сохраняется первое вхождение каждого элемента.

Пример

iex> Enum.uniq_by([{1, :x}, {2, :y}, {1, :z}], fn {x, _} -> x end)
[{1, :x}, {2, :y}]

iex> Enum.uniq_by([a: {:tea, 2}, b: {:tea, 2}, c: {:coffee, 1}], fn {_, y} -> y end)
[a: {:tea, 2}, c: {:coffee, 1}]

unzip(list)Source

@spec unzip(t()) :: {[element()], [element()]}

Обратная функция zip/2. Извлекает кортежи из двух элементов из заданного списка и группирует их вместе.

Принимает список элементов, являющихся кортежами из двух элементов, и возвращает кортеж из двух списков, каждый из которых сформирован из первого и второго элементов каждого кортежа соответственно.

Функция завершается неудачей, если список является или может быть преобразован в список кортежей с ровно двумя элементами в каждом кортеже.

Примеры

iex> Enum.unzip([{:a, 1}, {:b, 2}, {:c, 3}])
{[:a, :b, :c], [1, 2, 3]}

with_index(enumerable, fun_or_offset \\ 0)Source

@spec with_index(t(), integer()) :: [{term(), integer()}]
@spec with_index(t(), (element(), index() -> value)) :: [value] when value: any()

Возвращает перечислимый объект, где каждый элемент заключён в кортеж вместе с его индексом или в соответствии с заданной функцией.

Может принимать функцию или целое смещение.

Если задано смещение, индексация будет начинаться со значения смещения, а не с нуля.

Если задана функция, индексация будет происходить путём вызова функции для каждого элемента и индекса (нумерация с нуля) перечислимого объекта.

Примеры

iex> Enum.with_index([:a, :b, :c])
[a: 0, b: 1, c: 2]

iex> Enum.with_index([:a, :b, :c], 3)
[a: 3, b: 4, c: 5]

iex> Enum.with_index([:a, :b, :c], fn element, index -> {index, element} end)
[{0, :a}, {1, :b}, {2, :c}]

zip(enumerables)Source

@spec zip(enumerables) :: [tuple()] when enumerables: [t()] | t()

Комбинирует соответствующие элементы из конечного набора перечисляемых объектов в список кортежей.

Комбинирование завершается, как только какой-либо перечисляемый объект в заданном наборе завершает работу.

Примеры

iex> Enum.zip([[1, 2, 3], [:a, :b, :c], ["foo", "bar", "baz"]])
[{1, :a, "foo"}, {2, :b, "bar"}, {3, :c, "baz"}]

iex> Enum.zip([[1, 2, 3, 4, 5], [:a, :b, :c]])
[{1, :a}, {2, :b}, {3, :c}]

zip(enumerable1, enumerable2)Source

@spec zip(t(), t()) :: [{any(), any()}]

Комбинирует соответствующие элементы из двух перечисляемых объектов в список кортежей.

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

Комбинирование завершается, как только любой перечисляемый объект завершает работу.

Примеры

iex> Enum.zip([1, 2, 3], [:a, :b, :c])
[{1, :a}, {2, :b}, {3, :c}]

iex> Enum.zip([:a, :b, :c], [1, 2, 3])
[a: 1, b: 2, c: 3]

iex> Enum.zip([1, 2, 3, 4, 5], [:a, :b, :c])
[{1, :a}, {2, :b}, {3, :c}]

zip_reduce(enums, acc, reducer)Source

@spec zip_reduce(t(), acc, ([term()], acc -> acc)) :: acc when acc: term()

Выполняет редукцию над всеми заданными перечисляемыми объектами, останавливаясь, как только какой-либо перечисляемый объект становится пустым.

Функция редукции получит 2 аргумента: список элементов (по одному из каждого перечисляемого объекта) и накопитель.

На практике поведение, предоставляемое этой функцией, можно получить следующим образом:

Enum.reduce(Stream.zip(enums), acc, reducer)

Но `zip_reduce/3` существует для удобства.

Примеры

iex> enums = [[1, 1], [2, 2], [3, 3]]
...>  Enum.zip_reduce(enums, [], fn elements, acc ->
...>    [List.to_tuple(elements) | acc]
...> end)
[{1, 2, 3}, {1, 2, 3}]

iex> enums = [[1, 2], [a: 3, b: 4], [5, 6]]
...> Enum.zip_reduce(enums, [], fn elements, acc ->
...>   [List.to_tuple(elements) | acc]
...> end)
[{2, {:b, 4}, 6}, {1, {:a, 3}, 5}]
END_OF_DOCUMENT_MARKER

zip_reduce(left, right, acc, reducer)Source

@spec zip_reduce(t(), t(), acc, (enum1_elem :: term(), enum2_elem :: term(), acc ->
                             acc)) :: acc
when acc: term()

Сводит два перечислителя, останавливаясь, как только один из них становится пустым.

На практике поведение, предоставляемое этой функцией, можно получить с помощью:

Enum.reduce(Stream.zip(left, right), acc, reducer)

Но zip_reduce/4 существует для удобства.

Примеры

iex> Enum.zip_reduce([1, 2], [3, 4], 0, fn x, y, acc -> x + y + acc end)
10

iex> Enum.zip_reduce([1, 2], [3, 4], [], fn x, y, acc -> [x + y | acc] end)
[6, 4]

zip_with(enumerables, zip_fun)Source

@spec zip_with(t(), ([term()] -> term())) :: [term()]

Объединяет соответствующие элементы из конечного набора перечислителей в список, преобразуя их с помощью функции zip_fun по мере выполнения.

Первый элемент из каждого перечислителя в enumerables будет помещён в список, который затем передаётся одноаргументной функции zip_fun. Затем второй элемент из каждого перечислителя помещается в список и передаётся в zip_fun, и так далее, пока один из перечислителей в enumerables не исчерпает элементы.

Возвращает список со всеми результатами вызова zip_fun.

Примеры

iex> Enum.zip_with([[1, 2], [3, 4], [5, 6]], fn [x, y, z] -> x + y + z end)
[9, 12]

iex> Enum.zip_with([[1, 2], [3, 4]], fn [x, y] -> x + y end)
[4, 6]

zip_with(enumerable1, enumerable2, zip_fun)Source

@spec zip_with(t(), t(), (enum1_elem :: term(), enum2_elem :: term() -> term())) :: [
  term()
]

Объединяет соответствующие элементы из двух перечислителей в список, преобразуя их с помощью функции zip_fun по мере выполнения.

Соответствующие элементы из каждого набора передаются в предоставленную двухаргументную функцию zip_fun поочерёдно. Возвращает список, содержащий результат вызова zip_fun для каждой пары элементов.

Объединение завершается, как только один из перечислителей исчерпает элементы.

Объединение словарей

Важно помнить, что объединение по своей природе основано на порядке. Если вы объединяете два списка, вы получаете элемент в индексе из каждого списка по очереди. Если мы объединяем два словаря, то может показаться, что вы получите заданный ключ в левом словаре и соответствующий ключ в правом словаре, но нет никакой гарантии, потому что ключи словарей не упорядочены! Рассмотрим следующее:

left =  %{:a => 1, 1 => 3}
right = %{:a => 1, :b => :c}
Enum.zip(left, right)
# [{{1, 3}, {:a, 1}}, {{:a, 1}, {:b, :c}}]

Как вы можете видеть, :a не спаривается с :a. Если это то, что вам нужно, используйте Map.merge/3.

Примеры

iex> Enum.zip_with([1, 2], [3, 4], fn x, y -> x + y end)
[4, 6]

iex> Enum.zip_with([1, 2], [3, 4, 5, 6], fn x, y -> x + y end)
[4, 6]

iex> Enum.zip_with([1, 2, 5, 6], [3, 4], fn x, y -> x + y end)
[4, 6]

Скачать версию ePub

Создано с помощью ExDoc (v0.34.1) для языка программирования Elixir

© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.17.2/Enum.html

Spec-Zone.ru

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