在 Elixir 中,如何使用映射变量初始化结构
In Elixir how do you initialize a struct with a map variable
我知道可以通过 %User{ email: 'blah@blah.com' }
创建结构。但是如果我有一个变量 params = %{email: 'blah@blah.com'}
有没有办法使用该变量创建该结构,例如 %User{ params }
.
这给出了一个错误,只是想知道你是否可以爆炸它或其他方式?
您应该使用 struct/2
函数。来自文档:
defmodule User do
defstruct name: "john"
end
struct(User)
#=> %User{name: "john"}
opts = [name: "meg"]
user = struct(User, opts)
#=> %User{name: "meg"}
struct(user, unknown: "value")
#=> %User{name: "meg"}
另一种使用Map.merge/2
的方法:
示例:
params
#=> %{email: "blah@blah.com"}
%User{} |> Map.merge(params)
#=> %User{ email: 'blah@blah.com' }
前面的答案都很好,但有一个警告:结构中的键是原子,哈希中的键可能是字符串。使用 struct() 方法只会复制匹配的键,而字符串不会与原子匹配。示例:
defmodule User do
defstruct name: "john"
end
opts = %{"name" => "meg"}
user = struct(User, opts)
#=> %User{name: "john"}
使用合并也很奇怪,因为它会"undo"映射的结构性质:
user = Map.merge(%User{}, opts)
#=> %{:__struct__ => User, :name => "john", "name" => "meg"}
在 elixir-lang-talk Google 组上找到这个,来自何塞本人:
https://groups.google.com/d/msg/elixir-lang-talk/6geXOLUeIpI/L9einu4EEAAJ
That's pretty much the way to go except you can do everything in one pass:
def to_struct(kind, attrs) do
struct = struct(kind)
Enum.reduce Map.to_list(struct), struct, fn {k, _}, acc ->
case Map.fetch(attrs, Atom.to_string(k)) do
{:ok, v} -> %{acc | k => v}
:error -> acc
end
end
end
我知道可以通过 %User{ email: 'blah@blah.com' }
创建结构。但是如果我有一个变量 params = %{email: 'blah@blah.com'}
有没有办法使用该变量创建该结构,例如 %User{ params }
.
这给出了一个错误,只是想知道你是否可以爆炸它或其他方式?
您应该使用 struct/2
函数。来自文档:
defmodule User do
defstruct name: "john"
end
struct(User)
#=> %User{name: "john"}
opts = [name: "meg"]
user = struct(User, opts)
#=> %User{name: "meg"}
struct(user, unknown: "value")
#=> %User{name: "meg"}
另一种使用Map.merge/2
的方法:
示例:
params
#=> %{email: "blah@blah.com"}
%User{} |> Map.merge(params)
#=> %User{ email: 'blah@blah.com' }
前面的答案都很好,但有一个警告:结构中的键是原子,哈希中的键可能是字符串。使用 struct() 方法只会复制匹配的键,而字符串不会与原子匹配。示例:
defmodule User do
defstruct name: "john"
end
opts = %{"name" => "meg"}
user = struct(User, opts)
#=> %User{name: "john"}
使用合并也很奇怪,因为它会"undo"映射的结构性质:
user = Map.merge(%User{}, opts)
#=> %{:__struct__ => User, :name => "john", "name" => "meg"}
在 elixir-lang-talk Google 组上找到这个,来自何塞本人:
https://groups.google.com/d/msg/elixir-lang-talk/6geXOLUeIpI/L9einu4EEAAJ
That's pretty much the way to go except you can do everything in one pass:
def to_struct(kind, attrs) do struct = struct(kind) Enum.reduce Map.to_list(struct), struct, fn {k, _}, acc -> case Map.fetch(attrs, Atom.to_string(k)) do {:ok, v} -> %{acc | k => v} :error -> acc end end end