Recursion Elixir map_减少引用最后一个元素

Recursion Elixir map_减少引用最后一个元素,recursion,elixir,Recursion,Elixir,在与列表中的最后一个元素进行比较时,如何循环(递归地或使用reduce)一个映射的列表 例如,假设我有一个这样的地图列表: 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:

在与列表中的最后一个元素进行比较时,如何循环(递归地或使用
reduce
)一个
映射的
列表

例如,假设我有一个这样的地图列表:

    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)}]
            [%{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)}]
我想修改每个映射的
cluster
属性,以表示它所处的组(相对于它所处的顺序)

如果
集群
ID没有重复,那么使用
groupby
是很好的选择

我想在他们更改组时对他们进行分组,结果如下:

    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)}]
            [%{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

您需要在累加器中保留两个整数:当前生成的集群(每次更改都会增加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>}
]
[
%{a:0,集群:0,时间:#DateTime},
%{a:1,集群:0,时间:#DateTime},
%{a:2,集群:0,时间:#DateTime},
%{a:3,集群:0,时间:#DateTime},
%{a:4,集群:1,时间:#DateTime},
%{a:5,集群:1,时间:#DateTime},
%{a:6,集群:2,时间:#DateTime},
%{a:7,集群:2,时间:#DateTime},
%{a:8,集群:2,时间:#DateTime},
%{a:9,集群:3,时间:#DateTime},
%{a:10,集群:3,时间:#DateTime},
%{a:11,集群:3,时间:#DateTime},
%{a:12,集群:4,时间:#DateTime},
%{a:13,集群:4,时间:#DateTime}
]

更有效的方法是在map reducer中的函数子句上使用模式匹配:

Enum.map\u reduce(数据,{0,0},fn
%{cluster:last}=x,{i,last}->
{%{x |簇:i},{i,last}
%{cluster:last}=x,{i,{}->
{%{x |簇:i+1},{i+1,last}
(完)

没门!!我很好奇。我尝试在函数的第一个参数中放入两个参数,但失败了。我不知道您可以通过
元组将多个项传递到累加器中。累加器也可以进行
映射吗?或者需要什么吗?从中可以看出,它需要
any()
,这意味着如果需要,可以将最后一个结构完全传递给它。。。。六羟甲基三聚氰胺六甲醚。。。谢谢@Dogbert!!!是的,你可以传递任何术语。顺便说一句,我进一步简化了匿名函数中的代码。