我有一个enum
我正在使用group_by
。
Enum.group_by(my_list, fn x -> x.param end)
结果是它按param
值对其进行分组。我想快速模式匹配,所以我有:
%{"a" => a, "b" => b, "c" => c } = Enum.group_by(my_list, fn x -> x.param end)
但是当列表缺少“a”,“b”或“c”作为参数时,这会遇到问题。
请注意,我可以将其设置为变量,如果我访问它并且它不存在则会导致nil:
grouped = Enum.group_by(my_list, fn x -> x.param end)
grouped["a"] # this will show as nil or the result if it exists
但为了便于阅读,我想只是模式匹配并使用变量。这是Elixir不支持的东西吗?
答案 0 :(得分:1)
模式匹配用于自我检查断言代码,而不仅仅是快速获取值。您的代码会检查地图中是否存在所有指定的密钥。如果您不需要这样的检查,请不要使用模式匹配。
例如,让我们首先将结果分配给变量(实际上在Elixir中没有变化)。
groups = Enum.group_by(my_list, fn x -> x.param end)
然后让我们解决我们想要做的事情。我们想要处理这些群体吗?我们这样做:
Enum.map(groups, fn({name, list}) -> process_group(name, list) end)
我们需要处理缺失的群体吗?没问题:
missing_groups = Enum.filter(["a", "b", "c"], &(!Map.has_key?(groups, &1)))
Enum.map(missing_groups, fn(name) -> process_missing_group(name) end)
想要按键过滤?这也不是问题:
# 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"])
你真的想添加丢失的密钥吗?好吧,如果是这样,那就让我们做吧:
all_groups = Enum.into(["a", "b", "c"], %{}, &({&1, Map.get(groups, &1)}))
process_all_groups(all_groups)
如您所见,任何此操作都不需要地图的模式匹配。实际上,您根本不需要变量,只是为了便于阅读。
现在你可以说“好吧,好吧,但我想为不同的群体做不同的行动”。如果需要,您还可以使用模式匹配功能。
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)
这看起来像你需要的吗?