Hi group.
When working on sorting some data I realized that after sorting the
enumerable, I had to map and iterate again to do a data transformation
of the elements.
So I look for a function that would already do this and I cannot find
it. So by looking at the source code
https://github.com/elixir-lang/elixir/blob/1907914cf0d9d25b32373d3c8ad6b4b59877baaf/lib/elixir/lib/enum.ex#L3213-L3218
I see that it is already mapping after the sorting, in order to
return the original values.
So we are unnecessarily mapping once.
What I propose is introduce Enum.sort_by_transform/4 which takes a
transformer function and applies it to each element in the last map
iteration.
> sort_by_transform(enumerable, mapper, transformer, sorter)
>
> Sorts the mapped results of the `enumerable` according to
> the provided `sorter` function and later each element is tranformed
> by applying the `transformer` function. >>
After I'm done with the implementation I see in the documentation I
found that a new section has been added to the docs, (due to the
introduction of `List.keysort/3` in the development version of Elixir.
https://hexdocs.pm/elixir/main/Enum.html#sort_by/3-performance-characteristics
Coincidentally, the more performant solution that I proposes here does
exactly what the implementation of Enum.sort_by_transform/4 does.
https://github.com/eksperimental/elixir/commit/77c7bcea9348c0dfb16d0e94b2b5ba9d239a3cd5#diff-9a538f965f1fdc2cf9780b1008560f05bfa2ff80d145445abe37a0d70d3828a2R3219-R3230
So the example in the guide could be simplified as (after removing
the filtering of the id of the products, to make the example easier to
grasp)
Enum.sort_by_transform(products, & &1.price, & &
1.name)
Additionally (and optionally) I introduce Enum.map_sort_by/3 which
solves the common case of mapping and sorting in one go.
For example to sort the products alphabetically:
Enum.map_sort_by(products, & &
1.name)
You can see the full implementation here:
https://github.com/elixir-lang/elixir/compare/main...eksperimental:sort_by_transform
Please, let me know what you all think.