- I did this task using
iteraptor
libary, how can i do it using only elixir fuctionc not external libraries for example usingget_in/2
defmodule MapanalizTest do
use ExUnit.Case
doctest Mapanaliz
test "all_path_list(prev_result, xmap, prev_path)" do
assert Mapanaliz.all_path_list(%{}, []) == []
assert Mapanaliz.all_path_list(%{a1: 1}, []) == [[:a1]]
assert Mapanaliz.all_path_list(%{a1: 1, a2: 1}, []) == [[:a1], [:a2]]
assert Mapanaliz.all_path_list(%{a1: %{b1: 1}}, []) == [[:a1], [:a1, :b1]]
assert Mapanaliz.all_path_list(%{a1: 1, a2: %{b1: 1}}) == [[:a1], [:a2], [:a2, :b1]]
assert Mapanaliz.all_path_list(%{a1: 1, a2: %{a2b1: 1, a2b2: 1}}) ==
[[:a1], [:a2], [:a2, :a2b1], [:a2, :a2b2]]
assert Mapanaliz.all_path_list(%{a: %{c: 1, d: 1}, b: %{e: 1}}) ==
[[:a], [:b], [:a, :c], [:a, :d], [:b, :e]]
assert Mapanaliz.all_path_list(%{z1: %{y11: 1, y12: 1}, z2: %{y21: %{x221: 1}}}) ==
[[:z1], [:z2], [:z1, :y11], [:z1, :y12], [:z2, :y21], [:z2, :y21, :x221]]
end
end
- SOLUTION I did it like that using
Iteraptor
module, but how can i do that using only buildin functions
defmodule Mapanaliz do
def all_path_list(xmap) do
case xmap do
%{} -> []
end
xmap
|> Iteraptor.reduce([], fn {k, _}, acc ->
[Enum.join(k, ", ") | acc]
end, yield: :all)
|> :lists.reverse()
end
CodePudding user response:
Rather than a built-in function, this is typically a case for recursion since you want to iterate on a tree:
defmodule Mapanaliz do
def all_path_list(map, path \\ []) do
Enum.flat_map(map, fn {key, value} ->
new_path = path [key]
children = if is_map(value), do: all_path_list(value, new_path), else: []
[new_path | children]
end)
end
end
Explanation:
- we "loop" on the map keys and values
- if the value is not a map, we just add the current path
- if the value is a map, we get all its children paths by making a recursive call to
all_path_list
There are probably many ways to implement this using recursion.
Here I went with Enum.flat_map/2
because we want to merge all paths in a single list, not a list of lists.
But you can probably make it more efficient by passing a list accumulator and reversing the list at the end.