Packages
map_sorter
0.1.8
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).
¹_Or keywords or structures implementing the Access behaviour._
"""
require Logger
@doc """
Takes a list of `maps`¹ and either a list of `sort specs` or an AST
that will evaluate to a list of `sort specs` at runtime.
Returns the AST to sort the `maps`¹ as per the `sort specs`.
`sort specs` can be implicit, explicit or mixed:
- [:dob, :name] is _implicit_ and same as ⟹ [asc: :dob, asc: :name]
- [:dob, desc: :name] is _mixed_ and like ⟹ [asc: :dob, desc: :name]
- [asc: :dob, desc: :name] is _explicit_
¹_Or keywords or structures implementing the Access behaviour._
## Examples
iex> # Sorting maps...
iex> require MapSorter
iex> people = [
...> %{name: "Mike", likes: "ski, arts", dob: "1992-04-15"},
...> %{name: "Mary", likes: "travels" , dob: "1992-04-15"},
...> %{name: "Ann" , likes: "reading" , dob: "1992-04-15"},
...> %{name: "Ray" , likes: "cycling" , dob: "1977-08-28"},
...> %{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> 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: "1976-09-28"},
%{name: "Bill", likes: "karate" , dob: "1977-08-28"},
%{name: "Ray" , likes: "cycling" , dob: "1977-08-28"},
%{name: "Joe" , likes: "boxing" , dob: "1977-08-28"},
%{name: "Mary", likes: "travels" , dob: "1992-04-15"},
%{name: "Mike", likes: "ski, arts", dob: "1992-04-15"},
%{name: "Ann" , likes: "reading" , dob: "1992-04-15"}
]
iex> # Sorting keywords...
iex> require MapSorter
iex> people = [
...> [name: "Mike", likes: "ski, arts", dob: "1992-04-15"],
...> [name: "Mary", likes: "travels" , dob: "1992-04-15"],
...> [name: "Ann" , likes: "reading" , dob: "1992-04-15"],
...> [name: "Ray" , likes: "cycling" , dob: "1977-08-28"],
...> [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> fun = & &1
iex> MapSorter.log_level(:info) # :debug ⟹ debug messages
iex> sorted = %{
...> explicit: MapSorter.sort(people, asc: :dob, desc: :name),
...> mixed: MapSorter.sort(people, [:dob, desc: :name]),
...> runtime: MapSorter.sort(people, fun.([:dob, desc: :name]))
...> }
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: "1976-09-28"],
[name: "Ray" , likes: "cycling" , dob: "1977-08-28"],
[name: "Joe" , likes: "boxing" , dob: "1977-08-28"],
[name: "Bill", likes: "karate" , dob: "1977-08-28"],
[name: "Mike", likes: "ski, arts", dob: "1992-04-15"],
[name: "Mary", likes: "travels" , dob: "1992-04-15"],
[name: "Ann" , likes: "reading" , dob: "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