2016-12-30 35 views
1

我有一個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」爲PARAMS。

請注意,我可以將它設置爲一個變量,它會導致零,如果我訪問它,它不存在:

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

模式匹配_will_失敗的關鍵。您可以將'%{「a」=> nil,「b」=> nil,「c」=> nil}'與Enum.group_by的結果合併,但這可能比您提到的替代方案更糟。你也可以創建一個類似於'Map.take'的函數,它返回給定鍵的值,如果鍵不存在則返回'nil',並使用它:'[a,b,c] = my_take(Enum。 group_by(...),[「a」,「b」,「c」])''。 – Dogbert

+0

你所要求的東西是不被支持的,但是如果你稍微擴展你的問題(你想要怎麼處理這些數據?你爲什麼要返回'nil'?輸入列表是什麼樣的? )你可以得到一些更廣泛的建議。 –

回答

1

模式匹配用於自檢斷言代碼,而不僅僅是爲了快速獲取值。您的代碼將檢查映射中是否包含所有指定的鍵。如果你不需要這樣的檢查,那麼不要使用模式匹配。例如,我們首先將結果分配給一個變量(實際上它並不隨Elixir變化)。

groups = Enum.group_by(my_list, fn x -> x.param end) 

然後讓deсide我們想要與此有關。我們想要處理羣組嗎?讓我們這樣做:

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) 

這看起來像你需要什麼?

+0

我打算接受這個答案,因爲我要求的是不可能的,這提供了一些關於酏劑如何工作的有用信息 –

相關問題