是否有一个简单的方法来进行||在长生不老药中没有模式匹配?

时间:2016-12-30 10:39:46

标签: elixir

我有一个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不支持的东西吗?

1 个答案:

答案 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)

这看起来像你需要的吗?