Reputation: 1150
I have two lists with maps:
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"}]
and need to enumerate through the updates_list
, to put new key into each element in the apps
list to show if there are updates. i.e. Here there is new version for app1
, I need to add new_version: true/false
and get the desired result:
result = [%{name: "app1", version: "0.0.1", new_version: true},
%{name: "app2", version: "0.0.1", new_version: false}]
I have tried with the following function:
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)
and function:
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
But because it enumerates through all updates_map
for every app, it just overrides it, and I get no result. How can exit the loop, or preserve the changes to achieve the result
as above? Any advise appreciated!
Upvotes: 0
Views: 1329
Reputation: 222050
There's no need to write so much code if a O(n*m)
solution is acceptable and the criteria for a new version being present is just that an entry with the same name and different version exists in update_map
(this is what I think your code does). This can be done with just one for
and one nested 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
Output:
[%{name: "app1", new_version: true, version: "0.0.1"},
%{name: "app2", new_version: false, version: "0.0.1"}]
If you need this to run on a large number of apps and updates, you should probably convert the updates into some kind of Map so that the inner logic executes faster.
Upvotes: 2