Enum.sort_by
sort_by
, go back to Enum module for more information.
Specs
sort_by( t(), (element() -> mapped_element), (element(), element() -> boolean()) | :asc | :desc | module() | {:asc | :desc, module()} ) :: list() when mapped_element: element()
Sorts the mapped results of the enumerable
according to the provided sorter
function.
This function maps each element of the enumerable
using the
provided mapper
function. The enumerable is then sorted by
the mapped elements using the sorter
function, which defaults
to Kernel.<=/2
.
sort_by/3
differs from sort/2
in that it only calculates the
comparison value for each element in the enumerable once instead of
once for each element in each comparison. If the same function is
being called on both elements, it's more efficient to use sort_by/3
.
Examples
Using the default sorter
of <=/2
:
iex> Enum.sort_by(["some", "kind", "of", "monster"], &byte_size/1)
["of", "some", "kind", "monster"]
Sorting by multiple properties - first by size, then by first letter (this takes advantage of the fact that tuples are compared element-by-element):
iex> Enum.sort_by(["some", "kind", "of", "monster"], &{byte_size(&1), String.first(&1)})
["of", "kind", "some", "monster"]
Similar to sort/2
, you can pass a custom sorter:
iex> Enum.sort_by(["some", "kind", "of", "monster"], &byte_size/1, &>=/2)
["monster", "some", "kind", "of"]
Or use :asc
and :desc
:
iex> Enum.sort_by(["some", "kind", "of", "monster"], &byte_size/1, :desc)
["monster", "some", "kind", "of"]
As in sort/2
, avoid using the default sorting function to sort structs, as by default
it performs structural comparison instead of a semantic one. In such cases,
you shall pass a sorting function as third element or any module that implements
a compare/2
function. For example, to sort users by their birthday in both
ascending and descending order respectively:
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]}
]