我找到了一个在互联网上将地图转换为关键字列表的功能,但它不是递归的:
def to_keyword_list(dict) do
Enum.map(dict, fn({key, value}) -> {String.to_atom(key), value} end)
end
然后我做了这个,但它给了我一个错误。
def tokey(dict) do
Enum.map(dict, fn({key, value}) ->
if is_map value do
{String.to_atom(key), tokey(value)}
else
{String.to_atom(key), value}
end
end)
end
第一个结果:
["calig├╝eva": %{speeking: "speeeeeeee"}, test: "teet", tututu: "tururuuu"]
第二个结果:
** (ArgumentError) argument error
:erlang.binary_to_atom(:speeking, :utf8)
code.exs:10: anonymous fn/1 in Util.tokey/1
(elixir) lib/enum.ex:1233: anonymous fn/3 in Enum.map/2
(stdlib) lists.erl:1263: :lists.foldl/3
(elixir) lib/enum.ex:1772: Enum.map/2
code.exs:8: anonymous fn/1 in Util.tokey/1
(elixir) lib/enum.ex:1233: anonymous fn/3 in Enum.map/2
(stdlib) lists.erl:1263: :lists.foldl/3
有更简单或更有效的方法吗?为什么它会显示错误?我不能从内部调用函数吗?
第一次更改ü
的{{1}}的结果:
u
第二个输出相同的错误。这是我使用的地图:
[caligueva: %{speeking: "speeeeeeee"}, test: "teet", tututu: "tururuuu"]
答案 0 :(得分:2)
用于在Elixir中递归转换Maps
到Keyword Lists
:
defmodule MyMap do
def to_keyword_list(map) do
Enum.map(map, fn {k,v} ->
v = cond do
is_map(v) -> to_keyword_list(v)
true -> v
end
{String.to_atom("#{k}"), v}
end)
end
end
但正如@Dogbert已经提到的那样"Pure" Atoms cannot contain codepoints above 255,所以你的地图键应该是简单的字符串/原子:
iex(1)> MyMap.to_keyword_list(%{"caligueva" => %{speeking: "speeeeeeee"}, "test" => "teet", "tututu" => "tururuuu"})
[caligueva: [speeking: "speeeeeeee"], test: "teet", tututu: "tururuuu"]
答案 1 :(得分:2)
以下是重构的重构代码:
def map_to_keyword_list(map), do: convert(map)
defp convert(map) when is_map(map), do: Enum.map(map, fn {k,v} ->{String.to_atom(k),convert(v)} end)
defp convert(v), do: v