Enum.sort

You're seeing just the function sort, go back to Enum module for more information.

Specs

sort(t()) :: list()

Sorts the enumerable according to Erlang's term ordering.

This function uses the merge sort algorithm. Do not use this function to sort structs, see sort/2 for more information.

Examples

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

Specs

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

Sorts the enumerable by the given function.

This function uses the merge sort algorithm. The given function should compare two arguments, and return true if the first argument precedes or is in the same place as the second one.

Examples

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

The sorting algorithm will be stable as long as the given function returns true for values considered equal:

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

If the function does not return true for equal values, the sorting is not stable and the order of equal terms may be shuffled. For example:

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

Ascending and descending

sort/2 allows a developer to pass :asc or :desc as the sorting function, which is a convenience for <=/2 and >=/2 respectively.

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

Sorting structs

Do not use </2, <=/2, >/2, >=/2 and friends when sorting structs. That's because the built-in operators above perform structural comparison and not a semantic one. Imagine we sort the following list of dates:

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

Note that the returned result is incorrect, because sort/1 by default uses <=/2, which will compare their structure. When comparing structures, the fields are compared in alphabetical order, which means the dates above will be compared by day, month and then year, which is the opposite of what we want.

For this reason, most structs provide a "compare" function, such as Date.compare/2, which receives two structs and returns :lt (less-than), :eq (equal to), and :gt (greater-than). If you pass a module as the sorting function, Elixir will automatically use the compare/2 function of said module:

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

To retrieve all dates in descending order, you can wrap the module in a tuple with :asc or :desc as first element:

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