Some unsolicited remarks.
Apparently this isn’t unusual:
|> String.split(:binary.compile_pattern([":", ";"]), trim: true)
Without too much effort I found another, similar example:
Elixir Convert Query String Parameters into Map (Key/Value Pairs) · GitHub
Given the context this approach may be reasonable.
However on first blush that transformation would set a red flag for me on review. If I had to put it into words I would say:
The transformation is (willfully) disregarding the natural shape of the data (or it is ignoring the implied, natural boundaries/seams).
Effectively both “:
” and “;
” are treated as delimiters with identical meaning which isn’t the intention of the format. The test case didn’t make me feel any better. Without much imagination it could be rewritten as:
"build:1.2;branch:git_something_develop;branchname:weeble;woot:;key:value"
and the code as implemented would return:
%{"branch" => "git_something_develop", "branchname" => "weeble", "build" => "1.2", "woot" => "key"}
Well, that is never gonna happen …
Fine.
But for the sake of argument: valueless keys aren’t unheard of (e.g. disabled
, readonly
, required
attributes in an input
HTML tag). For the moment lets assume that we want to keep those keys - for example:
defp split_pairs(pair, list) do
case String.split(pair, ":") do
[key, value] ->
[{String.trim(key), String.trim(value)} | list]
_ ->
# ignore "non-pair"
list
end
end
defp to_key_values({key, ""}, list),
do: [{key, key} | list]
defp to_key_values({_, _} = key_value, list),
do: [key_value | list]
defp to_key_values(_, list),
# ignore values that "don't fit"
do: list
def split(metadata) do
metadata
|> String.split(";")
|> List.foldl([], &split_pairs/2)
|> List.foldl([], &to_key_values/2)
|> Map.new()
end
or when discarding valueless keys:
defp split_pairs1(pair, list) do
case String.split(pair, ":", trim: true) do
[key, value] ->
[{String.trim(key), String.trim(value)} | list]
_ ->
# ignore "non-pair"
list
end
end
def split1(metadata) do
metadata
|> String.split(";")
|> List.foldl([], &split_pairs1/2)
|> Map.new()
end
In my opinion both of these examples take (better) advantage of the natural, implied shape of the data. The other approach feels more like “smashing everything to bits and then picking up the pieces”.