Исходный код 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.
Обзор
Типы
- index()
Индекс, начиная с нуля. Также может быть отрицательным целым числом.
Функции
- 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)
Применяет отображение и сворачивание к перечислимому объекту, уплощая полученные результаты (только один уровень вложенности).
- frequencies(enumerable)
Возвращает карту с ключами как уникальными элементами
enumerableи значениями как количество каждого элемента.- frequencies_by(enumerable, key_fun)
Возвращает карту с ключами как уникальными элементами, полученными из
key_fun, и значениями как количество каждого элемента.- group_by(enumerable, key_fun, value_fun \\ fn x -> x end)
Разбивает перечислимый объект на группы на основе
enumerable.- intersperse(enumerable, separator)
Вставляет
separatorмежду каждым элементом перечисления.- into(enumerable, collectable)
Вставляет данный
enumerableвcollectable.- into(enumerable, collectable, transform)
Вставляет данный
enumerableвcollectableсогласно функции преобразования.- join(enumerable, joiner \\ "")
Объединяет данный
enumerableв строку, используяjoinerв качестве разделителя.- map(enumerable, fun)
Возвращает список, где каждый элемент является результатом вызова
funдля каждого соответствующего элементаenumerable.- map_every(enumerable, nth, fun)
Возвращает список результатов вызова
funдля каждогоnthэлементаenumerable, начиная с первого элемента.- map_intersperse(enumerable, separator, mapper)
Применяет отображение и вставляет разделитель для данного перечислимого объекта за один проход.
- map_join(enumerable, joiner \\ "", mapper)
Преобразует и объединяет заданный
enumerableв одном проходе.- map_reduce(enumerable, acc, fun)
Вызывает заданную функцию для каждого элемента в
enumerable, чтобы свести его к одному элементу, сохраняя накопитель.- max(enumerable, sorter \\ &>=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)
Возвращает максимальный элемент в
enumerableв соответствии с порядком Erlang.- max_by(enumerable, fun, sorter \\ &>=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)
Возвращает максимальный элемент в
enumerableсогласно вычислению заданнойfun.- member?(enumerable, element)
Проверяет, существует ли
elementвнутриenumerable.- min(enumerable, sorter \\ &<=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)
Возвращает минимальный элемент в
enumerableв соответствии с порядком Erlang.- min_by(enumerable, fun, sorter \\ &<=/2, empty_fallback \\ fn -> raise Enum.EmptyError end)
Возвращает минимальный элемент в
enumerableсогласно вычислению заданнойfun.- min_max(enumerable, empty_fallback \\ fn -> raise Enum.EmptyError end)
Возвращает кортеж с минимальным и максимальным элементами в перечисляемом согласно порядку Erlang.
- min_max_by(enumerable, fun, sorter_or_empty_fallback \\ &</2, empty_fallback \\ fn -> raise Enum.EmptyError end)
Возвращает кортеж с минимальным и максимальным элементами в перечисляемом, вычисленных с помощью заданной функции.
- product(enumerable)
Возвращает произведение всех элементов.
- random(enumerable)
Возвращает случайный элемент из
enumerable.- reduce(enumerable, fun)
Вызывает
funдля каждого элемента вenumerableс накопителем.- reduce(enumerable, acc, fun)
Вызывает
funдля каждого элемента вenumerableс накопителем.- reduce_while(enumerable, acc, fun)
Сводит
enumerableдо тех пор, покаfunне вернёт{:halt, term}.- reject(enumerable, fun)
Возвращает список элементов в
enumerableза исключением тех, для которых функцияfunвозвращает истинное значение.- reverse(enumerable)
Возвращает список элементов в
enumerableв обратном порядке.- 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(enumerables)
Объединяет соответствующие элементы из конечного набора перечислимых объектов в список кортежей.
- zip(enumerable1, enumerable2)
Объединяет соответствующие элементы из двух перечислимых объектов в список кортежей.
- zip_reduce(enums, acc, reducer)
Применяет reduce ко всем заданным перечислимым объектам, останавливаясь, как только какой-либо перечислимый объект окажется пустым.
- zip_reduce(left, right, acc, reducer)
Применяет reduce к двум перечислимым объектам, останавливаясь, как только один из перечислимых объектов станет пустым.
- zip_with(enumerables, zip_fun)
Объединяет соответствующие элементы из конечного набора перечислимых объектов в список, преобразуя их с помощью функции
zip_funпо мере выполнения.- zip_with(enumerable1, enumerable2, zip_fun)
Объединяет соответствующие элементы из двух перечислимых объектов в список, преобразуя их с помощью функции
zip_funпо мере выполнения.
Типы
Функции
all?(enumerable)Source
@spec all?(t()) :: boolean()
Возвращает true , если все элементы в enumerable истинны.
Когда элемент имеет ложное значение (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 , если fun.(element) истинно для всех элементов в enumerable.
Итерируется по enumerable и вызывает fun для каждого элемента. Если fun когда-либо возвращает ложное значение (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 , если enumerable пуста, независимо от fun. В пустом перечислимом нет элемента, для которого fun возвращает ложное значение, поэтому результат должен быть true. Это хорошо определенный логический аргумент для пустых коллекций.
any?(enumerable)Source
@spec any?(t()) :: boolean()
Возвращает true , если хотя бы один элемент в enumerable истинен.
Когда элемент имеет истинное значение (ни 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 , если fun.(element) истинно для хотя бы одного элемента в enumerable.
Итерируется по enumerable и вызывает fun для каждого элемента. Когда вызов fun возвращает истинное значение (ни 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()
Находит элемент по заданному index (нумерация с нуля).
Возвращает default , если index находится за пределами границ.
Можно передать отрицательное index, что означает, что enumerable перечисляется один раз, и index считает от конца (например, -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()]
Разбивает перечислимый по каждому элементу, для которого fun возвращает новое значение.
Возвращает список списков.
Примеры
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 элементов в enumerable.
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() Разбивает enumerable с точным управлением, когда каждый блок выдается.
chunk_fun получает текущий элемент и аккумулятор и должен вернуть:
-
{:cont, chunk, acc}для выдачи блока и продолжения с аккумулятором -
{:cont, acc}для того, чтобы не выдавать блок и продолжать с аккумулятором -
{:halt, acc}для остановки разбиения поenumerable.
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()
Принимая перечислимый перечислимых, конкатенирует enumerables в один список.
Примеры
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()
Возвращает размер enumerable.
Примеры
iex> Enum.count([1, 2, 3]) 3
count(enumerable, fun)Source
@spec count(t(), (element() -> as_boolean(term()))) :: non_neg_integer()
Возвращает количество элементов в enumerable, для которых fun возвращает истинное значение.
Примеры
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(), default(), (element() -> found_value)) :: found_value | default() when found_value: term()
Аналогично find/3, но возвращает значение вызова функции вместо самого элемента.
Значение считается найденным, когда результат является истинным (не nil и не false).
Примеры
iex> Enum.find_value([2, 3, 4], fn x -> ...> if x > 2, do: x * x ...> end) 9 iex> Enum.find_value([2, 4, 6], fn x -> rem(x, 2) == 1 end) nil iex> Enum.find_value([2, 3, 4], fn x -> rem(x, 2) == 1 end) true iex> Enum.find_value([1, 2, 3], "no bools!", &is_boolean/1) "no bools!"
flat_map(enumerable, fun)Source
@spec flat_map(t(), (element() -> t())) :: list()
Применяет данную 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()}) Применяет отображение и сокращение к enumerable, уплощая полученные результаты (только на один уровень).
Ожидает накопитель и функцию, которая принимает каждый элемент перечислимого объекта и должна возвращать кортеж, содержащий новый перечислимый объект (часто список) с новым накопителем или кортеж с :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}
iex> Enum.into([a: 2], %{a: 1, b: 3})
%{a: 2, b: 3} into(enumerable, collectable, transform)Source
@spec into(Enumerable.t(), Collectable.t(), (term() -> term())) :: Collectable.t()
Вставляет заданное 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()
Преобразует и объединяет данный перечислимый за один проход.
Если 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()} Вызывает заданную функцию для каждого элемента в перечислимом, чтобы свести его к одному элементу, сохраняя аккумулятор.
Возвращает кортеж, где первый элемент — преобразованный перечислимый, а второй — конечный аккумулятор.
Функция 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} 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 апреля, потому что структурное сравнение сравнивает день до года. По этой причине большинство структур предоставляют функцию «сравнения», такую как 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, означает, что сравнение структурное, а не семантическое. Поэтому, если вы хотите сравнивать структуры, большинство структур предоставляют функцию «сравнения», такую как 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]
Наконец, если вы не хотите вызывать исключение при пустом перечисляемом объекте, вы можете передать fallback для пустого объекта:
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]}
Наконец, если вы не хотите вызывать исключение при пустом перечисляемом объекте, вы можете передать fallback для пустого объекта:
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]}
}
Наконец, если вы не хотите вызывать исключение при пустом перечисляемом объекте, вы можете передать fallback для пустого объекта:
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
random(enumerable)Source
@spec random(t()) :: element()
Возвращает случайный элемент enumerable.
Вызывает исключение Enum.EmptyError, если enumerable пусто.
Эта функция использует модуль Erlang :rand для вычисления случайного значения. Просмотрите его документацию для настройки другого алгоритма случайности или другого начального значения.
Реализация основана на алгоритме выборки по резервуару enumerable. Предполагается, что возвращаемый образец может поместиться в памяти; входной 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 используется как начальное значение аккумулятора. Затем функция вызывается с последующим элементом и аккумулятором. Результат, возвращенный функцией, используется в качестве аккумулятора для следующей итерации рекурсивно. Когда перечисление завершается, возвращается последний аккумулятор.
Поскольку первый элемент перечисляемого объекта используется как начальное значение аккумулятора, 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
Reduce как строительный блок
Reduce (иногда называемый fold) — это базовый строительный блок в функциональном программировании. Почти все функции в модуле Enum могут быть реализованы на основе reduce. Эти функции часто опираются на другие операции, такие как Enum.reverse/1, которые оптимизированы в среде выполнения.
Например, мы можем реализовать map/2 в терминах reduce/3 следующим образом:
def my_map(enumerable, fun) do enumerable |> Enum.reduce([], fn x, acc -> [fun.(x) | acc] end) |> Enum.reverse() end
В примере выше, Enum.reduce/3 накапливает результат каждого вызова fun в список в обратном порядке, который правильно упорядочивается в конце с помощью вызова Enum.reverse/1.
Реализация функций, таких как map/2, filter/2 и других, — это хорошее упражнение для понимания мощности Enum.reduce/3. Когда операция не может быть выражена ни одной из функций в модуле Enum, разработчики, скорее всего, обратятся к reduce/3.
reduce_while(enumerable, acc, fun)Source
@spec reduce_while(t(), any(), (element(), any() -> {:cont, any()} | {:halt, any()})) ::
any() Уменьшает 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, или этот диапазон больше нормализованного index_range.last, тогда возвращается [].
Если используется шаг 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//1) []
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]] 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()
Берёт определённое количество элементов с начала или конца 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]
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]} 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-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.16.3/Enum.html