find key
: sum
innested map
and update its value to: bill * 100 : coins
Need to pass test1
test "test1" do
assert BcToInt.data(%{
count: 3,
sum: %{bills: 1, coins: 99},
tax: %{count: 3, sum: %{bills: 1, coins: 1}}
}) ==
%{count: 3, sum: 199, tax: %{count: 3, sum: 101}}
end
I tried to do it using Map_replace()
and checking value for nested map using is_map
and call function again if true
but how to get end result
def data(xmap) do
Enum.map(xmap, fn {_key, value} ->
keyy = :sum
aa = List.first(Map.values(xmap[keyy])) * 100 List.last(Map.values(xmap[keyy]))
if Map.has_key?(xmap, keyy) do
Map.replace(xmap, keyy, aa)
if is_map(value) do
data1(value)
end
end
end)
end
CodePudding user response:
Here's a version without using external libraries:
def data(map) do
map =
case map[:sum] do
%{bills: bills, coins: coins} -> %{map | sum: bills * 100 coins}
_ -> map
end
Map.new(map, fn
{k, v} when is_map(v) -> {k, data(v)}
entry -> entry
end)
end
Usage:
iex(1)> data = ...
%{
count: 3,
sum: %{bills: 1, coins: 99},
tax: %{count: 3, sum: %{bills: 1, coins: 1}}
}
iex(2)> BcToInt.data(data)
%{count: 3, sum: 199, tax: %{count: 3, sum: 101}}
CodePudding user response:
With a help of iteraptor
library:
Mix.install([:iteraptor])
Iteraptor.map(data, fn
{_k, %{bills: bills, coins: coins}} -> bills * 100 coins
# Is not `bill:` a typo?
{_k, %{bill: bills, coins: coins}} -> bills * 100 coins
other -> other
end, yield: :all)
#⇒ %{count: 3, sum: 199, tax: %{count: 3, sum: 101}}
CodePudding user response:
Your implementation correctly uses recursion to look into nested data structures. It looks like it's trying to use Map.replace/3
to try to modify the data structure in place, though. Elixir only has immutable data structures, so you need to construct a new map from the input rather than trying to update it in place.
I might implement the recursion here using pattern matching:
def data(%{bills: bills, coins: coins}) do
bills * 100 coins
end
def data(map) when is_map(map) do
Map.new(map, fn {k, v} -> {k, data(v)} end)
end
def data(any) do
any
end
With this setup, if data/1
is called with a map with the :bills
and :coins
keys (not necessarily in a field named :sum
) it adds them together; on any other map, it recurses through the values preserving the keys; and on any other value it returns the original value as-is.
CodePudding user response:
def data(xmap) do
keyy = :sum
aa = List.first(Map.values(xmap[keyy])) * 100
List.last(Map.values(xmap[keyy]))
Map.new(xmap, fn
{k, _v} when k == keyy -> {k, aa}
{k, v} when is_map(v) -> {k, data(v)}
{k, v} -> {k, v}
end)
end