Spec-Zone.ru › Elixir 1.15

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.map/2. Ведь если мы хотим пройти по каждому элементу списка, чем длиннее список, тем больше элементов нам нужно пройти, и тем дольше это займёт.

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

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

Типы

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

Индекс с нулевым основанием. Он также может быть отрицательным целым числом.

t()

Функции

all?(enumerable)

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

all?(enumerable, fun)

Возвращает true если fun.(element) истинно для всех элементов в enumerable.

any?(enumerable)

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

any?(enumerable, fun)

Возвращает true если fun.(element) истинно для хотя бы одного элемента в enumerable.

at(enumerable, index, default \\ nil)

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

chunk_by(enumerable, fun)

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

chunk_every(enumerable, count)

Короткая форма для chunk_every(enumerable, count, count).

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

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

chunk_while(enumerable, acc, chunk_fun, after_fun)

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

concat(enumerables)

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

concat(left, right)

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

count(enumerable)

Возвращает размер enumerable.

count(enumerable, fun)

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

count_until(enumerable, limit)

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

count_until(enumerable, fun, limit)

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

dedup(enumerable)

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

dedup_by(enumerable, fun)

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

drop(enumerable, amount)

Удаляет amount элементов из enumerable.

drop_every(enumerable, nth)

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

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)

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

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 в обратном порядке.

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.

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(перечисляемые)

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

zip(перечисляемый1, перечисляемый2)

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

zip_reduce(перечисляемые, acc, reducer)

Применяет reduce ко всем перечисляемым, останавливаясь, как только какой-либо перечисляемый становится пустым.

zip_reduce(левый, правый, acc, reducer)

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

zip_with(перечисляемые, zip_fun)

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

zip_with(перечисляемый1, перечисляемый2, 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

Как показывает последний пример, Enum.all?/2 возвращает true, если перечислимый объект пуст, независимо от fun. В пустом перечислимом объекте нет элемента, для которого fun возвращает ложное значение, поэтому результат должен быть 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()

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

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

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

Сокращение для chunk_every(enumerable, count, count).

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

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

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

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

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

Если :discard задано в leftover, последняя группа отбрасывается, если она не содержит ровно count элементов.

Примеры

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, chunk, acc} для формирования группы и продолжения с аккумулятивным значением
  • {:cont, acc} для отмены формирования группы и продолжения с аккумулятивным значением
  • {:halt, acc} для остановки разбиения по перечислимому объекту.

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

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

acc в after_fun требуется, чтобы отобразить формат кортежа из chunk_fun, но будет отброшен, так как итерация завершена.

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

Примеры

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

Подсчитывает перечисляемое, останавливаясь на limit.

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

Если перечисляемое реализует 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()

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

См. 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()

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

Элементы сравниваются с использованием ===/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()

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

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

Примеры

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

Удаляет amount элементов из enumerable.

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

Примеры

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

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

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

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

Примеры

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

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

Примеры

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

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

Возвращает :ok.

Примеры

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

empty?(enumerable)Source

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

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

Возвращает true, если enumerable пуст, иначе false.

Примеры

iex> Enum.empty?([])
true

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

fetch(enumerable, index)Source

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

Находит элемент с заданным index (с нулевой базой).

Возвращает {:ok, element}, если найден, иначе :error.

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

Находит элемент с заданным index (с нулевой базой).

Вызывает OutOfBoundsError, если заданный index находится вне диапазона enumerable.

Примеры

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

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

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

Примеры

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

Имейте в виду, что filter не способен одновременно фильтровать и преобразовывать элемент. Если вы хотите сделать это, рассмотрите использование 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()

Возвращает первый элемент, для которого fun возвращает истинное значение. Если такой элемент не найден, возвращает 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(), any(), (element() -> any())) :: any() | nil

Аналогично 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()

Преобразует заданный fun над enumerable и уплощает результат.

Эта функция возвращает новый перечислимый объект, созданный путём добавления результата вызова fun для каждого элемента enumerable вместе; концептуально это аналогично комбинации 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()})

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

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

Примеры

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

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

Примеры

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

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

Примеры

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

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

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

Примеры

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

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

Примеры

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

Вставляет заданный enumerable в collectable.

Обратите внимание, что передача непустого списка в качестве collectable устарела. Если вы собираете в непустой список ключевых слов, рассмотрите использование Keyword.merge(collectable, Enum.to_list(enumerable)). Если вы собираете в непустой список, рассмотрите что-то вроде Enum.to_list(enumerable) ++ collectable.

Примеры

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}

into(enumerable, collectable, transform)Source

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

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

Примеры

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(), String.t()) :: String.t()

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

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

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

Примеры

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

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

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

Примеры

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

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

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

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

Если nth равно 0, то enumerable непосредственно преобразуется в список без применения fun.

Примеры

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

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

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

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

Примеры

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

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

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

Функция fun получает два аргумента: первый — это элемент, а второй — накопитель. fun должна возвращать кортеж из двух элементов в формате {result, accumulator}.

Для карт первый элемент кортежа должен быть кортежем {key, value}.

Примеры

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

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

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

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

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

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

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

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

Членство проверяется с помощью оператора совпадения (===/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()

Возвращает минимальный элемент в enumerable в соответствии с порядком термов 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()

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

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

Вызывает предоставленную функцию empty_fallback и возвращает ее значение, если enumerable пусто. По умолчанию 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 и возвращает ее значение, если enumerable пусто. По умолчанию 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, если enumerable содержит нечисловое значение.

Примеры

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

random(enumerable)Source

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

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

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

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

Реализация основана на алгоритме выборки с замещением. Она предполагает, что возвращаемый элемент может поместиться в памяти; входной enumerable не обязательно должен, так как он просматривается только один раз.

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

Примеры

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

reduce(enumerable, fun)Source

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

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

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

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

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

Начальное значение накопителя — 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

Сведение как строительный блок

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

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

Ожидаемое возвращаемое значение fun —

  • {:cont, acc} для продолжения сводки с acc в качестве нового накопителя или
  • {:halt, acc} для остановки сводки

Если fun возвращает {:halt, acc} , сводка прекращается, и функция возвращает acc. В противном случае, если перечисляемый исчерпан, функция возвращает накопитель последней {:cont, 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()

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

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

Примеры

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

reverse(enumerable)Source

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

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

Примеры

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

reverse(enumerable, tail)Source

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

Инвертирует элементы в enumerable, добавляет 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()

Инвертирует enumerable в диапазоне от начального start_index до count элементов.

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

Примеры

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

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

Примеры

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

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

Примеры

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

shuffle(enumerable)Source

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

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

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

Примеры

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

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

slice(enumerable, index_range)Source

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

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

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

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

Если index_range.last выходит за границы, он присваивается как индекс последнего элемента.

Если нормализованный index_range.first выходит за пределы заданного enumerable, или этот enumerable больше нормализованного index_range.last, то возвращается [].

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

Примеры

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]

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

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

slice(enumerable, start_index, amount)Source

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

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

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

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

Возвращается [], если amount равен 0 или start_index выходит за границы.

Примеры

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

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

Семантика сдвигаемого диапазона совпадает с семантикой Enum.slice/2. В частности:

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

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

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

  • Убывающие диапазоны (например, 5..0//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()

Сортирует enumerable в соответствии с порядком 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()

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

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

Примеры

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

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

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

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

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

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

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

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

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 является отрицательным числом, оно начинает счёт с конца enumerable.

Обратите внимание, что отрицательное 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 содержит не числовое значение.

Примеры

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

Извлекает 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)
[3, 1]
iex> Enum.take_random(?a..?z, 5)
'mikel'

take_while(enumerable, fun)Source

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

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

Примеры

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

to_list(enumerable)Source

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

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

Примеры

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

uniq(enumerable)Source

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

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

Примеры

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

uniq_by(enumerable, fun)Source

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

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

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

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

Пример

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. Извлекает кортежи из двух элементов из данного enumerable и группирует их вместе.

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

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

Примеры

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

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

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

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

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

Если задано offset, оно будет индексировать со заданного смещения вместо нуля.

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

Примеры

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

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

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

Примеры

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

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

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

Функция reducer будет получать 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()]

Закачивает соответствующие элементы из конечного набора перечислимых в список, преобразуя их с помощью функции 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]

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.15.4/Enum.html

Spec-Zone.ru

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