Elixir / Phoenix退出循环

时间:2017-06-22 08:11:26

标签: elixir phoenix-framework enumeration

我有两张地图列表:

apps = [%{name: "app1", version: "0.0.1"}, %{name: "app2", version: "0.0.1"}]
updates_list = [%{name: "app1", version: "0.0.2"},
                %{name: "app2", version: "0.0.1"},
                %{name: "app3", version: "0.0.1"},
                %{name: "app4", version: "0.0.1"}]

并需要枚举updates_list,将新密钥放入apps列表中的每个元素,以显示是否有更新。即此处有app1的新版本,我需要添加new_version: true/false并获得所需的结果:

result = [%{name: "app1", version: "0.0.1", new_version: true},
          %{name: "app2", version: "0.0.1", new_version: false}]

我尝试过以下功能:

updates_map = Enum.map(updates_list, fn (x) -> Map.put(%{}, x.name, x.version ) end)
result = Enum.map(apps, fn (x) -> map_updates(x, updates_map) end)

和功能:

defp map_updates(app, updates_map) do
  app_map = Map.from_struct(app)
  for update <- updates_map do
    if Map.has_key?(update, app_map.name) do
      if Map.fetch(update, app_map.name) != app_map.version do
        app_map = app_map |> Map.put(:new_version, true)
      else
        app_map = app_map |> Map.put(:new_version, false) 
      end
    else
      app_map = app_map
    end 
  end
  app_map
end

但是因为它通过所有updates_map枚举每个应用程序,它只是覆盖它,我没有得到任何结果。如何退出循环,或保留更改以实现上述result?任何建议表示赞赏!

1 个答案:

答案 0 :(得分:2)

如果O(n*m)解决方案是可接受的,并且存在新版本的条件只是{{1}中存在具有相同名称和不同版本的条目,则无需编写如此多的代码1}}(这是我认为你的代码所做的)。只需一个update_map和一个嵌套for

即可完成此操作
Enum.any?

输出:

apps = [%{name: "app1", version: "0.0.1"}, %{name: "app2", version: "0.0.1"}]
updates_map = [%{name: "app1", version: "0.0.2"},
               %{name: "app2", version: "0.0.1"},
               %{name: "app4", version: "0.0.1"},
               %{name: "app4", version: "0.0.1"}]

updated_apps = for app <- apps do
  new_version = Enum.any?(updates_map, fn update ->
    app.name == update.name && app.version != update.version
  end)
  Map.put(app, :new_version, new_version)
end

IO.inspect updated_apps

如果您需要在大量应用程序和更新上运行,您应该将更新转换为某种类型的Map,以便内部逻辑执行得更快。