Reduce array that every element can have an array

You could write your own zip-longest.

defmodule Foo do
  def zip(a, b, c \\ [])

  def zip([], [], c), do: Enum.reverse(c)

  def zip([ha|ta], [], c) do
    zip(ta, [], [{ha, nil}|c])
  end

  def zip([], [hb|tb], c) do
    zip([], tb, [{hb, nil}|c])
  end

  def zip([ha|ta], [hb|tb], c) do
    zip(ta, tb, [{ha, hb}|c])
  end

  def transform(list) do
    Enum.flat_map(list, fn i ->
      i.ar1 |> zip(i.ar2) |> Enum.map(fn {ar1, ar2} ->
        %{name: i.name, ar1: ar1, ar2: ar2}
      end)
    end)
  end
end
iex(15)> a
[
  %{
    ar1: [%{name: "aa1"}, %{name: "aa2"}, %{name: "aa3"}],
    ar2: [%{department: "a23"}],
    name: "a1"
  },
  %{
    ar1: [%{name: "a22"}, %{name: "a32"}],
    ar2: [%{department: "a23"}, %{department: "a25"}],
    name: "a2"
  }
]
iex(16)> Foo.transform(a)
[
  %{ar1: %{name: "aa1"}, ar2: %{department: "a23"}, name: "a1"},
  %{ar1: %{name: "aa2"}, ar2: nil, name: "a1"},
  %{ar1: %{name: "aa3"}, ar2: nil, name: "a1"},
  %{ar1: %{name: "a22"}, ar2: %{department: "a23"}, name: "a2"},
  %{ar1: %{name: "a32"}, ar2: %{department: "a25"}, name: "a2"}
]
1 Like