Packages
map_sorter
0.2.47
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/cond.ex
defmodule MapSorter.Cond do
@moduledoc """
Generates cond clauses as a heredoc from a list of `sort specs`.
"""
import MapSorter.Container, only: [brackets: 1]
alias MapSorter.{SortSpec, SortSpecs}
@doc """
Generates cond clauses as a heredoc from a list of `sort specs`.
## Examples
iex> alias MapSorter.Cond
iex> sort_specs = [:name, {:desc, :dob}]
iex> Cond.clauses(sort_specs)
\"""
&1[:name] < &2[:name] -> true
&1[:name] > &2[:name] -> false
&1[:dob] > &2[:dob] -> true
&1[:dob] < &2[:dob] -> false
\"""
iex> alias MapSorter.Cond
iex> sort_specs = [:name, {:desc, {:dob, Date}}]
iex> Cond.clauses(sort_specs)
\"""
&1[:name] < &2[:name] -> true
&1[:name] > &2[:name] -> false
&1[:dob] != nil and Date.compare(&1[:dob], &2[:dob]) == :gt -> true
&1[:dob] != nil and Date.compare(&1[:dob], &2[:dob]) == :lt -> false
\"""
"""
@spec clauses(SortSpecs.t()) :: String.t()
def clauses(sort_specs) when is_list(sort_specs) do
Enum.map_join(sort_specs, &do_clauses/1)
end
## Private functions
# Use short-circuit 'and' to prevent compare if key not in map...
@spec cond(SortSpec.key(), String.t(), atom) :: String.t()
defp cond(key, module, op) when op in [:lt, :gt] do
"""
&1#{brackets(key)} != nil and\s
#{module}.compare(&1#{brackets(key)}, &2#{brackets(key)}) == #{inspect(op)}
"""
|> String.replace("\n", "")
end
@spec do_clauses(SortSpec.t()) :: String.t()
defp do_clauses({:asc, {key, module}}) when is_atom(module) do
with {:module, module} <- Code.ensure_loaded(module),
true <- function_exported?(module, :compare, 2) do
module = "#{inspect(module)}"
"""
#{cond(key, module, :lt)} -> true
#{cond(key, module, :gt)} -> false
"""
else
_no_module_or_function ->
key = {key, module}
"""
&1#{brackets(key)} < &2#{brackets(key)} -> true
&1#{brackets(key)} > &2#{brackets(key)} -> false
"""
end
end
defp do_clauses({:desc, {key, module}}) when is_atom(module) do
with {:module, module} <- Code.ensure_loaded(module),
true <- function_exported?(module, :compare, 2) do
module = "#{inspect(module)}"
"""
#{cond(key, module, :gt)} -> true
#{cond(key, module, :lt)} -> false
"""
else
_no_module_or_function ->
key = {key, module}
"""
&1#{brackets(key)} > &2#{brackets(key)} -> true
&1#{brackets(key)} < &2#{brackets(key)} -> false
"""
end
end
defp do_clauses({:asc, key}) do
"""
&1#{brackets(key)} < &2#{brackets(key)} -> true
&1#{brackets(key)} > &2#{brackets(key)} -> false
"""
end
defp do_clauses({:desc, key}) do
"""
&1#{brackets(key)} > &2#{brackets(key)} -> true
&1#{brackets(key)} < &2#{brackets(key)} -> false
"""
end
defp do_clauses({key, module}) when is_atom(module) do
do_clauses({:asc, {key, module}})
end
defp do_clauses(key) do
do_clauses({:asc, key})
end
end