# `Moar.Enum`
[🔗](https://github.com/synchronal/moar/blob/main/lib/enum.ex#L1)

Enum-related functions.

# `test_ids_opts`

```elixir
@type test_ids_opts() :: {:sorted, boolean()}
```

# `tids_opts`

```elixir
@type tids_opts() :: {:sorted, boolean()}
```

# `at!`

```elixir
@spec at!(Enum.t(), integer() | [integer()], any()) :: any()
```

Like `Enum.at/3` but raises if `index` is out of bounds.

# `compact`

```elixir
@spec compact(Enum.t()) :: Enum.t()
```

Removes nil elements from `enum`.

# `compact_blank`

```elixir
@spec compact_blank(Enum.t()) :: Enum.t()
```

Removes blank elements (as determined by `Moar.Term.blank?1`) from `enum`.

# `find_indices`

```elixir
@spec find_indices(Enum.t(), [any()], (any(), any() -&gt; boolean())) :: [integer()]
```

Returns the indices of `elements` in `enum`, using `fun` for comparisons (defaulting to `Kernel.==/2`)

```elixir
iex> Moar.Enum.find_indices(~w[apple banana cherry], ~w[cherry apple])
[2, 0]

iex> Moar.Enum.find_indices(~w[apple banana cherry], ~w[CHERRY APPLE], fn a, b ->
...>   String.downcase(a) == String.downcase(b)
...> end)
[2, 0]
```

# `find_indices!`

```elixir
@spec find_indices!(Enum.t(), [any()], (any(), any() -&gt; boolean())) :: [integer()]
```

Returns the indices of `elements` in `enum`, raising if any member of `elements` is not found.

```elixir
iex> Moar.Enum.find_indices!(~w[apple banana cherry], ~w[cherry apple])
[2, 0]

iex> Moar.Enum.find_indices!(~w[apple banana], ~w[cherry apple])
** (RuntimeError) Element "cherry" not present in:
["apple", "banana"]
```

# `first!`

```elixir
@spec first!(Enum.t()) :: any()
```

Returns the first item of `enum`, or raises if it is empty.

# `index_by`

```elixir
@spec index_by(Enum.t(), (any() -&gt; any())) :: map()
```

Converts an enum into a map of maps indexed by the return value of `index_fun`.
See also the similar map-specific `Moar.Map.index_by/2`.

```elixir
iex> Moar.Enum.index_by([%{name: "Alice", tid: "alice"}, %{name: "Billy", tid: "billy"}], & &1.tid)
%{"alice" => %{name: "Alice", tid: "alice"}, "billy" => %{name: "Billy", tid: "billy"}}
```

# `into!`

```elixir
@spec into!(nil | Enum.t(), Enum.t()) :: Enum.t()
```

Like `Enum.into` but accepts `nil` as the first argument

# `is_map_or_keyword`

> This function is deprecated. Use map_or_keyword?/1.

```elixir
@spec is_map_or_keyword(any()) :: boolean()
```

Deprecated in favor of `map_or_keyword?/1`.

# `is_map_or_nonempty_keyword`

> This function is deprecated. Use map_or_nonempty_keyword?/1.

```elixir
@spec is_map_or_nonempty_keyword(any()) :: boolean()
```

Deprecated in favor of `map_or_nonempty_keyword?/1`.

# `isort`

```elixir
@spec isort(Enum.t()) :: Enum.t()
```

Sorts `enum` case-insensitively. Uses `Enum.sort_by/3` under the hood.

# `isort_by`

```elixir
@spec isort_by(Enum.t(), (any() -&gt; any())) :: Enum.t()
```

Sorts `enum` case-insensitively by `mapper` function. Uses `Enum.sort_by/3` under the hood.

# `lists_to_maps`

```elixir
@spec lists_to_maps([[any()]], [any()] | :first_list) :: [map()]
```

Converts a list of lists to a list of maps with the given keys. The keys can be a list, or can be `:first_list`
which uses the first list in `list_of_lists` as the keys and the remaining lists in `list_of_lists` as the values.

```elixir
iex> Moar.Enum.lists_to_maps([[1, 2], [3, 4]], ["a", "b"])
[%{"a" => 1, "b" => 2}, %{"a" => 3, "b" => 4}]

iex> csv = [["a", "b"], [1, 2], [3, 4]]
iex> [headers | rows] = csv
iex> Moar.Enum.lists_to_maps(rows, headers)
[%{"a" => 1, "b" => 2}, %{"a" => 3, "b" => 4}]

iex> csv = [["a", "b"], [1, 2], [3, 4]]
iex> Moar.Enum.lists_to_maps(csv, :first_list)
[%{"a" => 1, "b" => 2}, %{"a" => 3, "b" => 4}]
```

# `map_or_keyword?`

```elixir
@spec map_or_keyword?(any()) :: boolean()
```

Returns true if the value is a map or a keyword list. This uses standard Elixir functions for determining
if a term is a map or a keyword, and therefore counts an empty list as a keyword list. See also
`map_or_nonempty_keyword?/1`.

This cannot be used as a guard because it uses `Keyword.keyword?` under the hood. Also, because of that,
it might scan an entire list to see if it's a keyword list, so it might be expensive.

# `map_or_nonempty_keyword?`

```elixir
@spec map_or_nonempty_keyword?(any()) :: boolean()
```

Like `map_or_keyword?/1` but returns false if the term is an empty list.

# `take_at`

```elixir
@spec take_at(Enum.t(), integer() | [integer()] | :all) :: any()
```

Returns a list of elements at the given indices, in the given order. If `:all` is given instead of a list of indices,
the entire enum is returned.

```elixir
iex> Moar.Enum.take_at(["A", "B", "C"], [0, 2])
["A", "C"]

iex> Moar.Enum.take_at(["A", "B", "C"], [2, 0])
["C", "A"]

iex> Moar.Enum.take_at(["A", "B", "C"], :all)
["A", "B", "C"]
```

# `test_ids`

```elixir
@spec test_ids(Enum.t(), [test_ids_opts()]) :: list()
```

Returns `:test_id` fields from `enumerable`.

This unusual function exists because the authors of Moar use test_ids extensively in tests.
See also `tids/2`.

# `tids`

```elixir
@spec tids(Enum.t(), [tids_opts()]) :: list()
```

Returns `:tid` fields from `enumerable`.

This unusual function exists because the authors of Moar use tids (test IDs) extensively in tests.
See also `test_ids/2`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
