How to dynamically create a Map key and add a list of lists as its value?

Hello.

I have the following maps list:

table = [
      %{column: "firstHeader", rows: ["a", "b", "c"], tableName: "table1"},
      %{column: "secondHeader", rows: ["d", "e", "f"], tableName: "table1"},
      %{column: "thirdHeader", rows: ["g", "h", "i"], tableName: "table1"},
      %{column: "fourthHeader", rows: ["j", "k", "l"], tableName: "table1"}
    ]

This is my desired output:

%{
    tableName: "table1",
    column: [
      "firstHeader",
      "secondHeader",
      "thirdHeader",
      "fourthHeader"
    ],
    rows: [
      ["a", "b", "c"],
      ["d", "e", "f"],
      ["g", "h", "i"],
      ["j", "k", "l"]
    ]
 }

So far I have only been able to solve the column field list.
I would like to know how to dynamically add the rows key and add their respective lists.

Currently this is my implementation.

Enum.reduce(table, %{}, fn table, map ->
  Map.merge(map, table, fn k, v1, v2 ->
    case k do
      :column -> List.flatten([v1, v2]) 
      :rows -> List.flatten([v1, v2])
      _ -> v2
    end
  end)
end)

Actual output:

%{
  tableName: "table1",
  column: [
    "firstHeader",
    "secondHeader",
    "thirdHeader",
    "fourthHeader"
  ],
  rows: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"]
}

Thanks.

table 
|> Enum.group_by(& &1.tableName) 
|> Enum.map(fn {k, v} -> 
  %{tableName: k, column: Enum.map(v, & &1.column), rows: Enum.map(v, & &1.rows)} 
end)
[
  %{
    column: ["firstHeader", "secondHeader", "thirdHeader", "fourthHeader"],
    rows: [["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"], ["j", "k", "l"]],
    tableName: "table1"
  }
]

It’s not exactly what You want as it returns a list, but it would work as well if You have multiple tableName.

If You want your expected output, You could retrieve the head.

5 Likes

@kokolegorille, thank you very much!