理解问题

塔伦

我想对一系列值组合执行一些分析。

我有以下函数,但是由于某种原因,在理解完成之后并且在函数主体的末尾,该变量analytics仍然是一个空列表,尽管它不在每次迭代的理解之内

有任何想法吗?

def handle_cast({:start}, state) do
    intervals = [7, 30, 90]
    groupings = ["day_of_week", "time_of_day"]
    aggregators = [
      %{
        domain: "support",
        metric: "new_conversations",
        func:   &App.get_new_conversations/2
      },
      %{
        domain: "support",
        metric: "closed_conversations",
        func:   &App.get_closed_conversations/2
      },
      %{
        domain: "support",
        metric: "median_response_time",
        func:   &App.get_median_response_time/2
      },
    ]

    Repo.transaction(fn ->
      Repo.delete_all(Analytic)

      analytics = []
      for interval <- intervals do
        for grouping <- groupings do
          for %{domain: domain, metric: metric, func: func} <- aggregators do
            analytic =
              func.(grouping, interval)
              |> Enum.map(fn %{"app_id" => app_id, "data" => data} = result ->
                %Analytic{app_id: app_id, domain: domain, metric: metric, grouping: grouping, interval_in_days: interval, data: data}
              end)

            analytics = [analytic|analytics]
          end
        end
      end
    end)

    {:noreply, state}
  end
多伯特

Elixir中的变量是不可变的,但可以重新绑定。这意味着该行analytics = [analytic|analytics]正在创建一个新列表,并将其绑定到analytics为该块的作用域命名的变量块结束时,更改不会保留在的下一次迭代中for例如:

iex(1)> x = 1
1
iex(2)> for i <- 1..3 do
...(2)>   IO.puts(x); x = x + i; IO.puts(x)
...(2)> end
1
2
1
3
1
4

对于您编写的代码,您可以使用以下事实:在其中for返回最后一个表达式的值的列表,并将最外面的表达式的返回值存储foranalytics,但是有一个小问题:您将得到嵌套列表:

iex(1)> for i <- 1..2 do
...(1)>   for j <- 1..2 do
...(1)>     for k <- 1..2 do
...(1)>       {i, j, k}
...(1)>     end
...(1)>   end
...(1)> end
[[[{1, 1, 1}, {1, 1, 2}], [{1, 2, 1}, {1, 2, 2}]],
 [[{2, 1, 1}, {2, 1, 2}], [{2, 2, 1}, {2, 2, 2}]]]

但是,有一个简单的解决方案!在一个调用中for接受多个<-子句,并自动返回一个平面列表:

iex(1)> for i <- 1..2, j <- 1..2, k <- 1..2 do
...(1)>   {i, j, k}
...(1)> end
[{1, 1, 1}, {1, 1, 2}, {1, 2, 1}, {1, 2, 2}, {2, 1, 1}, {2, 1, 2}, {2, 2, 1},
 {2, 2, 2}]

使用此方法,您的代码将变为:

analytics =
  for interval <- intervals,
      grouping <- groupings,
      %{domain: domain, metric: metric, func: func} <- aggregators do
      func.(grouping, interval)
      |> Enum.map(fn %{"app_id" => app_id, "data" => data} = result ->
        %Analytic{app_id: app_id, domain: domain, metric: metric, grouping: grouping, interval_in_days: interval, data: data}
      end)
    end
  end
end

这应该为您提供最有可能从原始代码中获得的相同输出。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章