如何在嵌套的多个地图中放置一个值(phoenix params)
How to put a value in multiple maps that are nested (phoenix params)
纯灵药问题:如何在嵌套在主地图中的地图中添加值?
嵌套地图的数量不固定。
在 Phoenix 上下文中,问题是如何在参数和嵌套参数中增加值。
如何从这里开始:
%{
"fname" => "",
"lname" => "",
"addresses" => %{
"0" => %{
"address" => ""
}
},
"phone_numbers" => %{
"0" => %{"number" => ""},
"1" => %{"number" => ""},
"2" => %{"number" => ""},
},
}
至:
%{
"account_id" => 2,
"fname" => "",
"lname" => "",
"addresses" => %{
"0" => %{
"account_id" => 2,
"address" => ""
}
},
"phone_numbers" => %{
"0" => %{"account_id" => 2,"number" => ""},
"1" => %{"account_id" => 2,"number" => ""},
"2" => %{"account_id" => 2,"number" => ""},
},
}
值 "account_id" => 2
已添加到主值和嵌套值。
参数可能有 "Phoenix" 方式,但我也在尝试考虑某种方式
Map.merge()
递归。
编辑:
phone_numbers
和 addresses
只是例子,我正在寻找一些通用的东西,其中子地图的键和子地图的数量是未知的。
披露:lens
的作者在这里。
我想不出只用内置 Access
来实现的方法,但你可以用 lens
库 (https://hex.pm/packages/lens) 实现:
data = %{
"fname" => "",
"lname" => "",
"addresses" => %{
"0" => %{
"address" => ""
}
},
"phone_numbers" => %{
"0" => %{"number" => ""},
"1" => %{"number" => ""},
"2" => %{"number" => ""}
}
}
data
|> put_in(
[
Lens.both(
Lens.root(),
Lens.keys(["addresses", "phone_numbers"]) |> Lens.map_values()
)
|> Lens.key("account_id")
],
2
)
|> IO.inspect()
# =>
%{
"account_id" => 2,
"addresses" => %{"0" => %{"account_id" => 2, "address" => ""}},
"fname" => "",
"lname" => "",
"phone_numbers" => %{
"0" => %{"account_id" => 2, "number" => ""},
"1" => %{"account_id" => 2, "number" => ""},
"2" => %{"account_id" => 2, "number" => ""}
}
}
Lens.both(
Lens.root(),
Lens.keys(["addresses", "phone_numbers"]) |> Lens.map_values()
)
|> Lens.key("account_id")
是关键位。它基本上说 "take every value under the key account_id FROM ((the whole data) AND (every map value in maps located under the keys addresses and phone_numbers))".
编辑:
OP 在评论中提到密钥可能无法预先知道。您可以在不明确指定它们的情况下实现相同的效果:
Lens.both(
Lens.root(),
Lens.map_values() |> Lens.filter(&is_map/1) |> Lens.map_values()
)
|> Lens.key("account_id")
如果您不介意 "account_id"
出现在中间映射中,最简单的方法可能是像这样编写一个递归函数:
defmodule AccountId do
def add(map, account_id) do
for {k, v} <- map, into: %{} do
if is_map(v) do
{k, add(v, account_id)}
else
{k, v}
end
end
|> Map.merge(%{"account_id" => account_id})
end
end
AccountId.add(data, 2) |> IO.inspect() # =>
%{
"account_id" => 2,
"addresses" => %{
"0" => %{"account_id" => 2, "address" => ""},
"account_id" => 2
},
"fname" => "",
"lname" => "",
"phone_numbers" => %{
"0" => %{"account_id" => 2, "number" => ""},
"1" => %{"account_id" => 2, "number" => ""},
"2" => %{"account_id" => 2, "number" => ""},
"account_id" => 2
}
}
纯灵药问题:如何在嵌套在主地图中的地图中添加值?
嵌套地图的数量不固定。
在 Phoenix 上下文中,问题是如何在参数和嵌套参数中增加值。
如何从这里开始:
%{
"fname" => "",
"lname" => "",
"addresses" => %{
"0" => %{
"address" => ""
}
},
"phone_numbers" => %{
"0" => %{"number" => ""},
"1" => %{"number" => ""},
"2" => %{"number" => ""},
},
}
至:
%{
"account_id" => 2,
"fname" => "",
"lname" => "",
"addresses" => %{
"0" => %{
"account_id" => 2,
"address" => ""
}
},
"phone_numbers" => %{
"0" => %{"account_id" => 2,"number" => ""},
"1" => %{"account_id" => 2,"number" => ""},
"2" => %{"account_id" => 2,"number" => ""},
},
}
值 "account_id" => 2
已添加到主值和嵌套值。
参数可能有 "Phoenix" 方式,但我也在尝试考虑某种方式
Map.merge()
递归。
编辑:
phone_numbers
和addresses
只是例子,我正在寻找一些通用的东西,其中子地图的键和子地图的数量是未知的。
披露:lens
的作者在这里。
我想不出只用内置 Access
来实现的方法,但你可以用 lens
库 (https://hex.pm/packages/lens) 实现:
data = %{
"fname" => "",
"lname" => "",
"addresses" => %{
"0" => %{
"address" => ""
}
},
"phone_numbers" => %{
"0" => %{"number" => ""},
"1" => %{"number" => ""},
"2" => %{"number" => ""}
}
}
data
|> put_in(
[
Lens.both(
Lens.root(),
Lens.keys(["addresses", "phone_numbers"]) |> Lens.map_values()
)
|> Lens.key("account_id")
],
2
)
|> IO.inspect()
# =>
%{
"account_id" => 2,
"addresses" => %{"0" => %{"account_id" => 2, "address" => ""}},
"fname" => "",
"lname" => "",
"phone_numbers" => %{
"0" => %{"account_id" => 2, "number" => ""},
"1" => %{"account_id" => 2, "number" => ""},
"2" => %{"account_id" => 2, "number" => ""}
}
}
Lens.both(
Lens.root(),
Lens.keys(["addresses", "phone_numbers"]) |> Lens.map_values()
)
|> Lens.key("account_id")
是关键位。它基本上说 "take every value under the key account_id FROM ((the whole data) AND (every map value in maps located under the keys addresses and phone_numbers))".
编辑:
OP 在评论中提到密钥可能无法预先知道。您可以在不明确指定它们的情况下实现相同的效果:
Lens.both(
Lens.root(),
Lens.map_values() |> Lens.filter(&is_map/1) |> Lens.map_values()
)
|> Lens.key("account_id")
如果您不介意 "account_id"
出现在中间映射中,最简单的方法可能是像这样编写一个递归函数:
defmodule AccountId do
def add(map, account_id) do
for {k, v} <- map, into: %{} do
if is_map(v) do
{k, add(v, account_id)}
else
{k, v}
end
end
|> Map.merge(%{"account_id" => account_id})
end
end
AccountId.add(data, 2) |> IO.inspect() # =>
%{
"account_id" => 2,
"addresses" => %{
"0" => %{"account_id" => 2, "address" => ""},
"account_id" => 2
},
"fname" => "",
"lname" => "",
"phone_numbers" => %{
"0" => %{"account_id" => 2, "number" => ""},
"1" => %{"account_id" => 2, "number" => ""},
"2" => %{"account_id" => 2, "number" => ""},
"account_id" => 2
}
}