在与列表中的最后一个元素进行比较时,如何循环(递归或使用reduce
)List
个Map
?
例如,假设我有一个这样的地图列表:
datetime = Timex.beginning_of_day(Timex.now)
data = [%{a: 0, cluster: 0, time: datetime},
%{a: 1, cluster: 0, time: Timex.shift(datetime, minutes: 3)},
%{a: 2, cluster: 0, time: Timex.shift(datetime, minutes: 6)},
%{a: 3, cluster: 0, time: Timex.shift(datetime, minutes: 9)},
%{a: 4, cluster: 1, time: Timex.shift(datetime, minutes: 12)},
%{a: 5, cluster: 1, time: Timex.shift(datetime, minutes: 15)},
%{a: 6, cluster: 0, time: Timex.shift(datetime, minutes: 18)},
%{a: 7, cluster: 0, time: Timex.shift(datetime, minutes: 21)},
%{a: 8, cluster: 0, time: Timex.shift(datetime, minutes: 23)},
%{a: 9, cluster: 2, time: Timex.shift(datetime, minutes: 26)},
%{a: 10, cluster: 2, time: Timex.shift(datetime, minutes: 29)},
%{a: 11, cluster: 2, time: Timex.shift(datetime, minutes: 32)},
%{a: 12, cluster: 1, time: Timex.shift(datetime, minutes: 35)},
%{a: 13, cluster: 1, time: Timex.shift(datetime, minutes: 38)}]
我想修改每个地图的cluster
属性,以表示它所处的组所在的组。
如果group_by
ID不重复,则使用cluster
非常有用。
我想在他们改变组时对它们进行分组,结果是这样的:
[%{a: 0, cluster: 0, time: datetime},
%{a: 1, cluster: 0, time: Timex.shift(datetime, minutes: 3)},
%{a: 2, cluster: 0, time: Timex.shift(datetime, minutes: 6)},
%{a: 3, cluster: 0, time: Timex.shift(datetime, minutes: 9)},
%{a: 4, cluster: 1, time: Timex.shift(datetime, minutes: 12)},
%{a: 5, cluster: 1, time: Timex.shift(datetime, minutes: 15)},
%{a: 6, cluster: 2, time: Timex.shift(datetime, minutes: 18)},
%{a: 7, cluster: 2, time: Timex.shift(datetime, minutes: 21)},
%{a: 8, cluster: 2, time: Timex.shift(datetime, minutes: 23)},
%{a: 9, cluster: 3, time: Timex.shift(datetime, minutes: 26)},
%{a: 10, cluster: 3, time: Timex.shift(datetime, minutes: 29)},
%{a: 11, cluster: 3, time: Timex.shift(datetime, minutes: 32)},
%{a: 12, cluster: 4, time: Timex.shift(datetime, minutes: 35)},
%{a: 13, cluster: 4, time: Timex.shift(datetime, minutes: 38)}]
为此,我需要将列表中的当前项与前一项进行比较。我已经开始使用这样的东西(下面)并停止,因为我知道它不会引用前一项来比较当前项目与前一项目:
Enum.map_reduce(data, 0, fn(x, acc) -> cluster_grouping(x, acc) end)
def cluster_grouping(x, acc) do
cond do
x.cluster == acc -> {Map.put(x, :cluster, acc), acc}
x.cluster > acc -> {Map.put(x, :cluster, acc), acc + 1}
end
end
答案 0 :(得分:1)
您需要在累加器中保留两个整数:当前生成的集群(每次更改时将增加1)和集群的最后一个原始值。
datetime = Timex.beginning_of_day(Timex.now)
data = [%{a: 0, cluster: 0, time: datetime},
%{a: 1, cluster: 0, time: Timex.shift(datetime, minutes: 3)},
%{a: 2, cluster: 0, time: Timex.shift(datetime, minutes: 6)},
%{a: 3, cluster: 0, time: Timex.shift(datetime, minutes: 9)},
%{a: 4, cluster: 1, time: Timex.shift(datetime, minutes: 12)},
%{a: 5, cluster: 1, time: Timex.shift(datetime, minutes: 15)},
%{a: 6, cluster: 0, time: Timex.shift(datetime, minutes: 18)},
%{a: 7, cluster: 0, time: Timex.shift(datetime, minutes: 21)},
%{a: 8, cluster: 0, time: Timex.shift(datetime, minutes: 23)},
%{a: 9, cluster: 2, time: Timex.shift(datetime, minutes: 26)},
%{a: 10, cluster: 2, time: Timex.shift(datetime, minutes: 29)},
%{a: 11, cluster: 2, time: Timex.shift(datetime, minutes: 32)},
%{a: 12, cluster: 1, time: Timex.shift(datetime, minutes: 35)},
%{a: 13, cluster: 1, time: Timex.shift(datetime, minutes: 38)}]
Enum.map_reduce(data, {0, 0}, fn x, {i, last} ->
i = if x.cluster == last, do: i, else: i + 1
{Map.put(x, :cluster, i), {i, x.cluster}}
end)
|> elem(0)
|> IO.inspect
输出:
[
%{a: 0, cluster: 0, time: #DateTime<2018-02-18 00:00:00Z>},
%{a: 1, cluster: 0, time: #DateTime<2018-02-18 00:03:00Z>},
%{a: 2, cluster: 0, time: #DateTime<2018-02-18 00:06:00Z>},
%{a: 3, cluster: 0, time: #DateTime<2018-02-18 00:09:00Z>},
%{a: 4, cluster: 1, time: #DateTime<2018-02-18 00:12:00Z>},
%{a: 5, cluster: 1, time: #DateTime<2018-02-18 00:15:00Z>},
%{a: 6, cluster: 2, time: #DateTime<2018-02-18 00:18:00Z>},
%{a: 7, cluster: 2, time: #DateTime<2018-02-18 00:21:00Z>},
%{a: 8, cluster: 2, time: #DateTime<2018-02-18 00:23:00Z>},
%{a: 9, cluster: 3, time: #DateTime<2018-02-18 00:26:00Z>},
%{a: 10, cluster: 3, time: #DateTime<2018-02-18 00:29:00Z>},
%{a: 11, cluster: 3, time: #DateTime<2018-02-18 00:32:00Z>},
%{a: 12, cluster: 4, time: #DateTime<2018-02-18 00:35:00Z>},
%{a: 13, cluster: 4, time: #DateTime<2018-02-18 00:38:00Z>}
]
答案 1 :(得分:0)
更多的elixirish方法是在map-reducer中的函数子句上使用模式匹配:
Enum.map_reduce(data, {0, 0}, fn
%{cluster: last} = x, {i, last} ->
{%{x | cluster: i}, {i, last}}
%{cluster: last} = x, {i, _} ->
{%{x | cluster: i + 1}, {i + 1, last}}
end)