Spec-Zone.ru › Elixir 1.18

Исходный код 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 элементов в enumerable.

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)

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

dedup_by(enumerable, fun)

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

drop(enumerable, amount)

Опускает amount элементов из enumerable.

drop_every(enumerable, nth)

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

END_OF_DOCUMENT_MARKER
drop_while(enumerable, fun)

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

each(enumerable, fun)

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

empty?(enumerable)

Определяет, является ли последовательность пустой.

fetch(enumerable, index)

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

fetch!(enumerable, index)

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

filter(enumerable, fun)

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

find(enumerable, default \\ nil, fun)

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

find_index(enumerable, fun)

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

find_value(enumerable, default \\ nil, fun)

Аналогично find(enumerable, default, fun), но возвращает значение вызова функции вместо самого элемента.

flat_map(enumerable, fun)

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

flat_map_reduce(enumerable, acc, fun)

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

frequencies(enumerable)

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

frequencies_by(enumerable, key_fun)

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

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

Разбивает последовательность на группы на основе ключей.

intersperse(enumerable, separator)

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

into(enumerable, collectable)

Вставляет данную последовательность в коллекцию.

into(enumerable, collectable, transform)

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

join(enumerable, joiner \\ "")

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

map(enumerable, fun)

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

map_every(enumerable, nth, fun)

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

map_intersperse(enumerable, separator, mapper)

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

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

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

map_reduce(enumerable, acc, fun)

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

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

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

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

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

member?(enumerable, element)

Проверяет, существует ли элемент в перечислителе.

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

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

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

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

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)

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

product_by(enumerable, mapper)

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

random(enumerable)

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

reduce(enumerable, fun)

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

reduce(enumerable, acc, fun)

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

reduce_while(enumerable, acc, fun)

Рекурсивно сокращает перечислитель, пока функция не вернёт false.

reject(enumerable, fun)

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

END_OF_DOCUMENT_MARKER
reverse(enumerable)

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

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)

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

sum_by(enumerable, mapper)

Преобразует и суммирует заданное enumerable за один проход.

take(enumerable, amount)

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

take_every(enumerable, nth)

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

take_random(enumerable, count)

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

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()

Функции

all?(enumerable)Source

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

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

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

Примеры

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()

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

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

Примеры

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 возвращает true, если перечислитель пуст, независимо от функции. В пустом перечислителе нет элемента, для которого функция возвращает ложное значение, поэтому результат должен быть true. Это хорошо определённое логическое утверждение для пустых коллекций.

any?(enumerable)Source

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

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

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

Примеры

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()

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

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

Примеры

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()

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

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

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

Примеры

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()]

Является сокращением для Enum.chunk_by/2.

END_OF_DOCUMENT_MARKER

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

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

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

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

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

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

Примеры

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 получает текущий элемент и аккумулятор и должен вернуть:

  • true для вывода фрагмента и продолжения с аккумулятором
  • false для того, чтобы не выводить фрагмент и продолжить с аккумулятором
  • nil для остановки разбиения по перечислимому объекту.

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

  • true для вывода фрагмента. Фрагмент будет добавлен в список уже выведенных фрагментов.
  • false для того, чтобы не выводить фрагмент

acc в after_fun нужен для отражения формата кортежа из 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()

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

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

Примеры

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()

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

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

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

Примеры

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()

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

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

Если нужно удалить все дублирующиеся элементы, независимо от порядка, см. 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]
END_OF_DOCUMENT_MARKER

each(enumerable, fun)Source

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

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

Возвращает nil.

Примеры

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.

Можно передать отрицательный индекс, что означает, что перечисление перебирается один раз, а индекс подсчитывается с конца (например, `fetch(list, -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()

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

Возбуждает исключение `**IndexError**`, если заданный индекс находится вне диапазона перечисления.

Примеры

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, но возвращает значение вызова функции вместо самого элемента.

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

Примеры

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]]

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

iex> Enum.flat_map([4, 0, 2, 0], fn x ->
...>   if x != 0, do: [1 / x], else: []
...> end)
[0.25, 0.5]

flat_map_reduce(enumerable, acc, fun)Source

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

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

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

Примеры

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()

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

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

Примеры

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`. Если вы собираете в непустой список, рассмотрите что-то вроде `Enum.into(list, [])`.

Примеры

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

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}

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.

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

Если перечисляемый объект пуст, вызывается предоставленная функция. По умолчанию функция вызывает 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()

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

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

Вызывает предоставленную функцию и возвращает её значение, если перечисляемый объект пуст. По умолчанию функция вызывает 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()

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

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

Примеры

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/2` и `in/2` работают, используя эту функцию.

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.

По умолчанию сравнение выполняется с помощью функции сортировки <=. Если несколько элементов считаются минимальными, возвращается первый найденный. Если вы хотите, чтобы возвращался последний элемент, считающийся минимальным, функция сортировки не должна возвращать 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, которая получает две структуры и возвращает :lt (меньше), :eq (равно) и :gt (больше). Если вы передаёте модуль как функцию сортировки, Elixir автоматически будет использовать функцию compare/2 указанного модуля:

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()

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

По умолчанию сравнение выполняется с помощью функции сортировки <=. Если несколько элементов считаются минимальными, возвращается первый найденный. Если вы хотите, чтобы возвращался последний элемент, считающийся минимальным, функция сортировки не должна возвращать 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, которая получает две структуры и возвращает :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_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}

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}

Тот факт, что эта функция использует порядок терминов Erlang, означает, что сравнение является структурным, а не семантическим. Поэтому, если вы хотите сравнить структуры, большинство структур предоставляют функцию «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, если перечислимый объект содержит нечисловое значение.

Если вам нужно сначала применить преобразование, рассмотрите использование Enum.product_by/2 вместо этого.

Примеры

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

product_by(enumerable, mapper)Source

@spec product_by(t(), (element() -> number())) :: number()

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

Вызывает исключение ArithmeticError, если функция mapper возвращает нечисловое значение.

Примеры

iex> Enum.product_by([%{count: 2}, %{count: 4}, %{count: 3}], fn x -> x.count end)
24

iex> Enum.product_by(1..3, fn x -> x ** 2 end)
36

iex> Enum.product_by([], fn x -> x.count end)
1

Фильтрация может быть достигнута путем возврата 1 для игнорирования элементов:

iex> Enum.product_by([2, -1, 3], fn x -> if x > 0, do: x, else: 1 end)
6

random(enumerable)Source

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

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

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

Эта функция использует модуль Erlang :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()

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

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

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

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

Если вы хотите использовать другое значение для аккумулятора, используйте 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()

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

Начальное значение аккумулятора — 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 (иногда называемый fold) — это базовый строительный блок в функциональном программировании. Почти все функции в модуле Enum могут быть реализованы на основе reduce. Эти функции часто полагаются на другие операции, такие как Enum.reverse/1, которые оптимизированы в runtime.

Например, мы можем реализовать 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 для продолжения уменьшения с acc в качестве нового аккумулятора или
  • false для остановки уменьшения

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

Примеры

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()

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

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

Примеры

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

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 для вычисления случайного значения. Обратитесь к его документации, чтобы настроить другой алгоритм генерации случайных чисел или другое начальное значение.

Примеры

Примеры ниже используют псевдослучайный алгоритм :exsss, так как это значение по умолчанию от 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()

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

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

Индексы нормализуются, то есть отрицательные индексы считаются с конца (например, -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]

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

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()

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

Семантика перемещаемого диапазона соответствует семантике Enum.slice/2. Это означает:

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

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

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

  • Убывающие диапазоны (например, `(1..-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 towards the head of the list
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 towards the tail of the list
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]

sort(enumerable, sorter)Source

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

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

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

Примеры

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

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

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

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

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

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

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

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

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

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

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 по умолчанию использует <=, которое будет сравнивать их структуру. При сравнении структур поля сравниваются в алфавитном порядке, что означает, что даты выше будут сравниваться по дню, месяцу и затем году, что является обратным тому, что мы хотим.

По этой причине большинство структур предоставляют функцию "compare", такую как Date.compare/2, которая принимает две структуры и возвращает -1 (меньше), 0 (равно) и 1 (больше). Если вы передадите модуль в качестве функции сортировки, 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]]

Чтобы получить все даты в порядке убывания, вы можете обернуть модуль в кортеж с `-1` или `~w` в качестве первого элемента:

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]]
END_OF_DOCUMENT_MARKER

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()

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

Эта функция отображает каждый элемент enumerable с помощью предоставленной функции mapper. Затем перечисляемый объект сортируется по отображённым элементам с помощью sorter, по умолчанию :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]

Примеры

Используя по умолчанию sorter :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/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.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()}

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

Если 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()}

Разделяет перечисляемый объект на две части в позиции элемента, для которого fun возвращает ложное значение (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], []}

split_with(enumerable, fun)Source

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

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

Разделяет заданный enumerable на два списка, вызывая fun с каждым элементом в enumerable в качестве единственного аргумента. Возвращает кортеж с первым списком, содержащим все элементы в enumerable, для которых применение fun вернуло истинное значение, и вторым списком со всеми элементами, для которых применение fun вернуло ложное значение (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, если enumerable содержит нечисловое значение.

Если вам нужно применить преобразование предварительно, рассмотрите использование Enum.sum_by/2 вместо этого.

Примеры

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

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

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

sum_by(enumerable, mapper)Source

@spec sum_by(t(), (element() -> number())) :: number()

Картирует и суммирует заданный enumerable за один проход.

Вызывает исключение ArithmeticError, если mapper возвращает нечисловое значение.

Примеры

iex> Enum.sum_by([%{count: 1}, %{count: 2}, %{count: 3}], fn x -> x.count end)
6

iex> Enum.sum_by(1..3, fn x -> x ** 2 end)
14

iex> Enum.sum_by([], fn x -> x.count end)
0

Фильтрацию можно выполнить, вернув 0 для игнорирования элементов:

iex> Enum.sum_by([1, -2, 3], fn x -> if x > 0, do: x, else: 0 end)
4

take(enumerable, amount)Source

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

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

Если задано положительное amount, оно берет amount элементов с начала enumerable.

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

Если amount равно 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()

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

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

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

Примеры

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()

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

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

См. 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"
END_OF_DOCUMENT_MARKER

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}]

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()]

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

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

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

Примеры

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()
]

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

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

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

Комбинирование словарей

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

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.36.1) для языка программирования Elixir

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

Spec-Zone.ru

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