Packages
map_sorter
0.2.35
0.2.70
0.2.69
0.2.68
0.2.67
0.2.66
0.2.65
0.2.64
0.2.63
0.2.62
0.2.61
0.2.60
0.2.59
0.2.58
0.2.57
0.2.56
0.2.55
0.2.54
0.2.53
0.2.52
0.2.51
0.2.50
0.2.49
0.2.48
0.2.47
0.2.46
0.2.45
0.2.44
0.2.42
0.2.41
0.2.40
0.2.39
0.2.38
0.2.37
0.2.36
0.2.35
0.2.34
0.2.33
0.2.32
0.2.31
0.2.30
0.2.29
0.2.28
0.2.27
0.2.26
0.2.25
0.2.24
0.2.23
0.2.22
0.2.21
0.2.20
0.2.19
0.2.18
0.2.17
0.2.16
0.2.15
0.2.14
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.22
0.1.21
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Sorts a list of maps per a list of sort specs.
Current section
Files
Jump to
Current section
Files
lib/map_sorter.ex
defmodule MapSorter do
@moduledoc """
Sorts a list of `maps` per a list of `sort specs`.
Also supports:
- keywords
- structs implementing the Access behaviour
- nested maps, keywords or structs implementing the Access behaviour
"""
alias __MODULE__.{Log, SortSpecs}
@doc """
Sorts `maps` per the given `sort specs` (compile time or runtime).
Examples of `sort specs` for flat data structures:
```
- implicit: [:dob, :name]
- mixed: [:dob, desc: :name]
- explicit: [asc: :dob, desc: :name]
```
Examples of `sort specs` with a `Date` key for flat data structures:
```
- implicit: [{:dob Date}, :name]
- mixed: [{:dob Date}, desc: :name]
- explicit: [asc: {:dob Date}, desc: :name]
```
Examples of `sort specs` for nested data structures:
```
- implicit: [[:birth, :date], :name]
- mixed : [[:birth, :date], desc: :name]
- explicit: [asc: [:birth, :date], desc: :name]
```
Examples of `sort specs` with a `Date` key for nested data structures:
```
- implicit: [{[:birth, :date], Date}, :name]
- mixed: [{[:birth, :date], Date}, desc: :name]
- explicit: [asc: {[:birth, :date], Date}, desc: :name]
```
## Examples
iex> require MapSorter
iex> people = [
...> %{name: "Mike", likes: "movies" , dob: "1992-04-15"},
...> %{name: "Mary", likes: "travels", dob: "1992-04-15"},
...> %{name: "Bill", likes: "karate" , dob: "1977-08-28"},
...> %{name: "Joe" , likes: "boxing" , dob: "1977-08-28"},
...> %{name: "Jill", likes: "cooking", dob: "1976-09-28"}
...> ]
iex> sort_specs = Tuple.to_list({:dob, {:desc, :likes}})
iex> sorted_people = %{
...> explicit: MapSorter.sort(people, asc: :dob, desc: :likes),
...> mixed: MapSorter.sort(people, [:dob, desc: :likes]),
...> runtime: MapSorter.sort(people, sort_specs)
...> }
iex> sorted_people.explicit == sorted_people.mixed and
...> sorted_people.explicit == sorted_people.runtime and
...> sorted_people.explicit
[
%{name: "Jill", likes: "cooking", dob: "1976-09-28"},
%{name: "Bill", likes: "karate" , dob: "1977-08-28"},
%{name: "Joe" , likes: "boxing" , dob: "1977-08-28"},
%{name: "Mary", likes: "travels", dob: "1992-04-15"},
%{name: "Mike", likes: "movies" , dob: "1992-04-15"}
]
"""
defmacro sort(maps, sort_specs) do
specs =
case sort_specs do
specs when is_list(specs) ->
# [asc: {:dob, {:__aliases__, [line: 7], [:Date]}}] =>
# [asc: {:dob, Date}]
{specs, []} = Code.eval_quoted(specs)
specs
specs ->
# In case any module attributes...
Macro.expand(specs, __CALLER__)
end
:ok = Log.debug(:sort_specs, {sort_specs, specs, __ENV__, __CALLER__})
case SortSpecs.to_quoted(specs) do
{:ok, fun_ast} ->
quote do: Enum.sort(unquote(maps), unquote(fun_ast))
{:error, invalid_specs} ->
:ok = Log.error(:invalid_specs, {invalid_specs, __ENV__, __CALLER__})
maps
end
end
end