2016-10-20 37 views
0

如何映射和減少仙丹列表並將其轉換爲新列表的方法是什麼?如何在Elixir中映射和減少地圖列表

要求: 1.查找具有相同ID的地圖: 2.合併「角色」鍵值(即收集所有唯一值)。 3.對於所有其他地圖(列表元素),什麼也不做。

list = [%{"id": 1, "role": ["A", "B"]}, %{"id": 2, "role": ["B", "C"]}, %{"id": 1, "role": ["C", "A"]} ] 

需要被轉換在以下列表:

ans_list = [%{"id": 1, "role": ["A", "B", "C"]}, %{"id": 2, "role": ["B", "C"]}] 

回答

3

可以由id使用Enum.group_by/2到組,則對於每個組,通過roleEnum.flat_map/2Enum.uniq/1

list = [%{"id": 1, "role": ["A", "B"]}, %{"id": 2, "role": ["B", "C"]}, %{"id": 1, "role": ["C", "A"]} ] 

list 
|> Enum.group_by(&(&1.id)) 
|> Enum.map(fn {key, value} -> 
    %{id: key, role: value |> Enum.flat_map(&(&1.role)) |> Enum.uniq} 
end) 
|> IO.inspect 

輸出:

[%{id: 1, role: ["A", "B", "C"]}, %{id: 2, role: ["B", "C"]}] 

如在下面評論的要求,這裏是如何保存所有鍵/值對,只修改組的第一個項目的role

list = [%{"id": 1, "role": ["A", "B"], "somekey": "value of the key 1"}, 
     %{"id": 2, "role": ["B", "C"], "somekey": "value of the key 2"}, 
     %{"id": 1, "role": ["C", "A"], "somekey": "value of the key 3"}] 

list 
|> Enum.group_by(&(&1.id)) 
|> Enum.map(fn {_, [value | _] = values} -> 
    %{value | role: values |> Enum.flat_map(&(&1.role)) |> Enum.uniq} 
end) 
|> IO.inspect 

輸出:

[%{id: 1, role: ["A", "B", "C"], somekey: "value of the key 1"}, 
%{id: 2, role: ["B", "C"], somekey: "value of the key 2"}] 
+0

當我們有多個鍵值對時,獲得相同結果的好方法是什麼! 例如 [%{「id」:1,「role」:[「A」,「B」],「somekey」:「key的值」},%{「id」:2, :[「B」,「C」],「somekey」:「鍵的值」},%{「id」:1,「role」:[「C」,「A」],「somekey」鍵值「}] 而我們不想改變其他鍵的值。 – arpit

+0

如果'somekey'的值對於兩個具有相同'id'的地圖是不同的? – Dogbert

+0

偉大的觀察。 我試圖讓所有具有相同id的元素都需要縮小所有uniq角色。但與此同時,我還有其他幾個(實際上是6個)其他鍵值對,這些鍵值對不應該改變。如果兩個記錄具有不同的鍵值對,那麼我們可以保留具有最低值的那個記錄,或者我們可以保留第一個地圖的鍵值。 我在看'Enum.map_reduce'和'Enum.reduce',但努力找出解決方案。 – arpit