查找
nested map
中的键: sum
并将其值更新为: bill * 100 + : coins
需要通过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
我试图使用Map_replace()
和使用is_map
检查嵌套映射的值,如果true
再次调用函数,但如何获得最终结果
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
下面是一个不使用外部库的版本:
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
用法:
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}}
借助iteraptor
库:
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}}
您的实现正确地使用递归来查看嵌套的数据结构。不过,它看起来像是在尝试使用Map.replace/3
来尝试修改数据结构。Elixir只有不可变的数据结构,所以你需要从输入中构造一个新的映射,而不是试图就地更新它。
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
在这样的设置下,如果data/1
被调用时带有:bills
和:coins
键的映射(不一定在名为:sum
的字段中),它会将它们加在一起;在任何其他map上,它通过保留键的值递归;对于任何其他值,它返回原始值
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