Packages
map_sorter
0.1.12
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` as per a list of `sort specs`
(ascending/descending keys).
Also works for keywords or structures implementing the Access behaviour.
"""
require Logger
@doc """
Sorts the `maps` as per the `sort specs` (compile time or runtime).
`sort specs` can be implicit, explicit or mixed:
- [:dob, :name] - _implicit_ ≡ [_asc:_ :dob, _asc:_ :name]
- [:dob, desc: :name] - _mixed_ ≡ [_asc:_ :dob, desc: :name]
- [asc: :dob, desc: :name] - _explicit_
## Examples
iex> require MapSorter
iex> people = [
...> %{name: "Mike", likes: "movies" , dob: ~D[1992-04-15]},
...> %{name: "Mary", likes: "travels", dob: ~D[1992-04-15]},
...> %{name: "Ann" , likes: "reading", dob: ~D[1992-04-15]},
...> %{name: "Ray" , likes: "cycling", dob: ~D[1977-08-28]},
...> %{name: "Bill", likes: "karate" , dob: ~D[1977-08-28]},
...> %{name: "Joe" , likes: "boxing" , dob: ~D[1977-08-28]},
...> %{name: "Jill", likes: "cooking", dob: ~D[1976-09-28]}
...> ]
iex> fun = & &1
iex> MapSorter.log_level(:info) # :debug → debug messages
iex> sorted = %{
...> explicit: MapSorter.sort(people, asc: :dob, desc: :likes),
...> mixed: MapSorter.sort(people, [:dob, desc: :likes]),
...> runtime: MapSorter.sort(people, fun.([:dob, desc: :likes]))
...> }
iex> MapSorter.log_level(:info) # :info → no debug messages
iex> sorted.explicit == sorted.mixed and
...> sorted.explicit == sorted.runtime and
...> sorted.explicit
[
%{name: "Jill", likes: "cooking", dob: ~D[1976-09-28]},
%{name: "Bill", likes: "karate" , dob: ~D[1977-08-28]},
%{name: "Ray" , likes: "cycling", dob: ~D[1977-08-28]},
%{name: "Joe" , likes: "boxing" , dob: ~D[1977-08-28]},
%{name: "Mary", likes: "travels", dob: ~D[1992-04-15]},
%{name: "Ann" , likes: "reading", dob: ~D[1992-04-15]},
%{name: "Mike", likes: "movies" , dob: ~D[1992-04-15]}
]
"""
defmacro sort(maps, sort_specs) do
Logger.debug("sort specs: #{inspect(sort_specs)}...")
sort_fun_ast =
case sort_specs do
specs when is_list(specs) -> specs
specs -> Macro.expand(specs, __CALLER__) # in case module attribute
end
|> MapSorter.Support.sort_fun_ast()
quote do: Enum.sort(unquote(maps), unquote(sort_fun_ast))
end
@doc """
Allows to change the log `level` at compile time.
"""
defmacro log_level(level), do: Logger.configure(level: level)
end