转换待办事项列表并集中任务

时间:2017-09-29 09:51:28

标签: elixir

我有一份待办事项清单:

[
  {%{date_value: ~D[2017-01-01], weekday: 7}, %{todo: "a", priority: 1}},
  {%{date_value: ~D[2017-01-01], weekday: 7}, %{todo: "b", priority: 2}},
  {%{date_value: ~D[2017-01-01], weekday: 7}, %{todo: "c", priority: 3}},
  {%{date_value: ~D[2017-01-02], weekday: 1}, nil},
  {%{date_value: ~D[2017-01-03], weekday: 2}, %{todo: "d", priority: 2}},
]

但我需要一个这样的清单:

[
  %{date_value: ~D[2017-01-01], weekday: 7, tasks: [%{todo: "a", priority: 1}, 
                                                   %{todo: "b", priority: 2}, 
                                                   %{todo: "c", priority: 3}]},
  %{date_value: ~D[2017-01-02], weekday: 1, tasks: []},
  %{date_value: ~D[2017-01-03], weekday: 2, tasks: [%{todo: "d", priority: 2}]}
]

如何将第一个版本转换为第二个版本?

我理解[head | tail]是一种递归遍历此列表以编译新列表的方法。但我不明白如何从这一次递归中收集所有todo以便将它们组合到自己的列表中。

1 个答案:

答案 0 :(得分:3)

首先,按日期组件对列表进行分组,值函数仅返回任务。这将创建从日期组件到任务列表的Map。然后,将地图转换回列表,在此过程中还会移除nil值,因为您根据示例输出不需要它们。

list = [
  {%{date_value: ~D[2017-01-01], weekday: 7}, %{todo: "a", priority: 1}},
  {%{date_value: ~D[2017-01-01], weekday: 7}, %{todo: "b", priority: 2}},
  {%{date_value: ~D[2017-01-01], weekday: 7}, %{todo: "c", priority: 3}},
  {%{date_value: ~D[2017-01-02], weekday: 1}, nil},
  {%{date_value: ~D[2017-01-03], weekday: 2}, %{todo: "d", priority: 2}},
]

list
|> Enum.group_by(fn {date, _} -> date end, fn {_, task} -> task end)
|> Enum.map(fn {date, tasks} ->
  date |> Map.put(:tasks, Enum.filter(tasks, &(&1)))
end)
|> IO.inspect

输出:

[%{date_value: ~D[2017-01-01],
   tasks: [%{priority: 1, todo: "a"}, %{priority: 2, todo: "b"},
    %{priority: 3, todo: "c"}], weekday: 7},
 %{date_value: ~D[2017-01-02], tasks: [], weekday: 1},
 %{date_value: ~D[2017-01-03], tasks: [%{priority: 2, todo: "d"}], weekday: 2}]

(地图是无序的,因此此输出与预期输出相同。)