2016-10-20 11 views
0

elixirのリストをマップして縮小し、新しいリストに変換するには、どのような方法が良いですか?マップ方法と縮小方法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

あなたがEnum.flat_map/2Enum.uniq/1roleを渡し、その後、グループごとに、idによってグループにEnum.group_by/2を使用することができます。

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、 "役割":["A"、 "B"]、 "somekey": "キーの値"}、%{"id":2、 "role" "%" "id":1、 "role":["C"、 "A"] "somekey": "キーの値"キーの値 "}] そして、他のキーの値を変更する必要はありません。 – arpit

+0

'somekey'の値が同じ' id'を持つ2つのマップで異なる場合はどうなりますか? – Dogbert

+0

素晴らしい観察。 私は、同じidを持ち、縮小する必要があるすべての要素を取得しようとしていますが、すべてのユニークな役割を組み合わせています。しかし同時に、私はいくつかの(実際には6つの)他のキーと値のペアがありますが、それらは変更すべきではありません。 2つのレコードが異なるキーと値のペアを持つ場合、最小値を保持するか、最初のマップのキー値を保持できます。 私は 'Enum.map_reduce'と' Enum.reduce'を見ていますが、解決策を見つけ出すのに苦労しています。 – arpit

関連する問題