Reputation: 11173
I have an enum
that I am using group_by
with.
Enum.group_by(my_list, fn x -> x.param end)
The result is that it groups it by the param
value. I would like to pattern match on that quickly so I have:
%{"a" => a, "b" => b, "c" => c } = Enum.group_by(my_list, fn x -> x.param end)
But this runs into issues when list is missing either "a", "b", or "c" as params.
Notice that I can set it to a variable and it will result in nil if I access it and it doesnt exist:
grouped = Enum.group_by(my_list, fn x -> x.param end)
grouped["a"] # this will show as nil or the result if it exists
But for readability, I wanted to just pattern match and use the variables. Is this something that is unsupported in Elixir?
Upvotes: 1
Views: 3317
Reputation: 5481
Pattern matching is for self-checking assertive code, not just for getting values quickly. Your code checks if there are all specified keys in the map. If you don't need such a check then don't use pattern matching.
For example, let's first assign the result to a variable (which does not vary in Elixir, actually).
groups = Enum.group_by(my_list, fn x -> x.param end)
Then let's deсide what we want to do with this. Do we want to process the groups? Let's do it:
Enum.map(groups, fn({name, list}) -> process_group(name, list) end)
Do we need to process the missing groups? No problem:
missing_groups = Enum.filter(["a", "b", "c"], &(!Map.has_key?(groups, &1)))
Enum.map(missing_groups, fn(name) -> process_missing_group(name) end)
Want to filter by keys? That's not a problem too:
# First variant:
filtered_groups = Enum.into(Enum.filter(groups, fn({k, v}) -> k in ["a", "b", "c"] end), %{})
# Second variant:
filtered_groups = Map.drop(groups, ["d", "e", "f", "g", "h"])
Do you really want to add missing keys? Ok, if so then let's do it:
all_groups = Enum.into(["a", "b", "c"], %{}, &({&1, Map.get(groups, &1)}))
process_all_groups(all_groups)
As you can see, pattern matching for map is not really needed for any of this action. Actually, you don't need the variables at all, they are just for readability.
Now you can say "ok, ok, but I want to do different actions for different groups". This is where you can also use the pattern matching feature if needed.
def process_group(name, nil), do: action_empty(name)
def process_group("a", list), do: action_a(list)
def process_group("b", list), do: action_b(list)
def process_group(name, [x]), do: single_lement_action(name, x)
def process_group(name, list), do: another_action(name, list)
Does this look like what you need?
Upvotes: 1