Hey guys, how can I improve this code?
I have a list of keys I will have to get with their values from a map and its sub-maps.
For example, I have the following map:
%{a: 1, b: 1, c: %{d: 1, e: 1}}
The result I need is:
%{a: 1, c: %{e: 1}}
I have it working now. I did something similar to the following code, but it does not look like the best way:
Map.take(name_map, [
:a,
])
|> Map.put(
:c,
Map.take(name_map.c, [
:e
])
)```
Thank you in advance!
It’s hard to make specific suggestions without more information about why some of the decisions are being made (why keep :a
but not :b
? why keep :e
but not :d
?), but some general thoughts:
- combinations of
Map.get
(or some_map.key
) and Map.put
with the same key can usually be made clearer with Map.update
- if you’re doing a lot of complex map manipulation, take a look at the
Access
module and supporting functions (get_in
etc)
2 Likes
Since it wasn’t explicitly shown what this list of keys looks like, I came up with my own way of declaring the keys used to traverse a nested map.
defmodule Extracter do
def extract(source, keys), do: extract(source, keys, %{})
defp extract(_source, [], dest), do: dest
defp extract(source, [{key, children} | rest], dest) do
Map.put(extract(source, rest, dest), key, extract(source[key], children, %{}))
end
defp extract(source, [key | rest], dest) do
Map.put(extract(source, rest, dest), key, source[key])
end
end
source = %{a: 1, b: 1, c: %{d: 1, e: 1}}
keys = [:a, {:c, [:e]}]
Extracter.extract(source, keys)
# %{a: 1, c: %{e: 1}}
1 Like
That’s exactly what I was looking for.
Thank you, guys!