Converting a list of maps into a list of tuples

Given:

defmodule Foo do

  def main do
    fast_cars =
    [
      %{color: "Red", make: "Mclaren", mileage: 15641.469},
      %{color: "Blue", make: "Ferrari", mileage: 120012.481},
      %{color: "Red", make: "Ferrari", mileage: 29831.021},
      %{color: "Black", make: "Ferrari", mileage: 24030.674},
      %{color: "Cobalt", make: "Ferrari", mileage: 412.811},
      %{color: "Blue", make: "Koenigsegg", mileage: 250.762},
      %{color: "Cobalt", make: "Koenigsegg", mileage: 1297.76},
      %{color: "Titanium", make: "Koenigsegg", mileage: 5360.336},
      %{color: "Blue", make: "Maserati", mileage: 255.78}
    ]

    Enum.map(
      fast_cars,
      fn element -> Map.to_list(element)
      |> List.to_tuple
    end)

  end

end

Desired output:

   [
      {color: "Red", make: "Mclaren", mileage: 15641.469},
      {color: "Blue", make: "Ferrari", mileage: 120012.481},
      {color: "Red", make: "Ferrari", mileage: 29831.021},
      {color: "Black", make: "Ferrari", mileage: 24030.674},
      {color: "Cobalt", make: "Ferrari", mileage: 412.811},
      {color: "Blue", make: "Koenigsegg", mileage: 250.762},
      {color: "Cobalt", make: "Koenigsegg", mileage: 1297.76},
      {color: "Titanium", make: "Koenigsegg", mileage: 5360.336},
      {color: "Blue", make: "Maserati", mileage: 255.78}
    ]

Here’s what I’m getting instead:


iex(1)> Foo.main 
[
  {{:color, "Red"}, {:make, "Mclaren"}, {:mileage, 15641.469}},
  {{:color, "Blue"}, {:make, "Ferrari"}, {:mileage, 120012.481}},
  {{:color, "Red"}, {:make, "Ferrari"}, {:mileage, 29831.021}},
  {{:color, "Black"}, {:make, "Ferrari"}, {:mileage, 24030.674}},
  {{:color, "Cobalt"}, {:make, "Ferrari"}, {:mileage, 412.811}},
  {{:color, "Blue"}, {:make, "Koenigsegg"}, {:mileage, 250.762}},
  {{:color, "Cobalt"}, {:make, "Koenigsegg"}, {:mileage, 1297.76}},
  {{:color, "Titanium"}, {:make, "Koenigsegg"}, {:mileage, 5360.336}},
  {{:color, "Blue"}, {:make, "Maserati"}, {:mileage, 255.78}}
]

Assuming this is possible, how should Foo.main be corrected to get the desired output? Thanks so much for your concrete guidance! :slight_smile:

1 Like

It is not possible… A tuple cannot look like this.

2 Likes

What’s your use case? Maybe we can help you come up with an alternative.

1 Like

Thanks for clarifying :slight_smile:

Thanks so much for your offer! :slight_smile:

What I’d like to do is take each map in that list of maps and insert it into an ETS table as it’s own individual record. Since :ets.insert only works with tuples -based on my limited experience with ETS- my instinct was to simply take each map, convert it to a tuple and then use something like Enum.each(main(), fn element -> :ets.insert(:fast_cars_cache, element) end) to update the table.

How would you suggest I go about doing this?

Tuples are not meant to be key value like… but record like.

One solution is to store like this…

{"Red", "Mclaren", 15641.469}

and assume position 1 is color, position 2 is make etc.

2 Likes

ETS requires tuples but a map can be part of the tuple. The only requirement is that the first element be some sort of key.

1 Like

@ kokolegorille

Thank you both for your insights!


defmodule Foo do

  def main do
    fast_cars =
    [
      %{color: "Red", make: "Mclaren", mileage: 15641.469},
      %{color: "Blue", make: "Ferrari", mileage: 120012.481},
      %{color: "Red", make: "Ferrari", mileage: 29831.021},
      %{color: "Black", make: "Ferrari", mileage: 24030.674},
      %{color: "Cobalt", make: "Ferrari", mileage: 412.811},
      %{color: "Blue", make: "Koenigsegg", mileage: 250.762},
      %{color: "Cobalt", make: "Koenigsegg", mileage: 1297.76},
      %{color: "Titanium", make: "Koenigsegg", mileage: 5360.336},
      %{color: "Blue", make: "Maserati", mileage: 255.78}
    ]

    Enum.map(
      fast_cars,
      fn %{color: color, make: make, mileage: mileage}
      ->
        {make, %{color: color, mileage: mileage}}
      end)

  end


  def update_ETS_table do
    if Enum.member?(:ets.all(), :fast_cars_cache) do
      :ets.delete(:fast_cars_cache)
      :ets.new(:fast_cars_cache, [:duplicate_bag, :public, :named_table])
      Enum.each(main(), fn element -> :ets.insert(:fast_cars_cache, element) end)
    else
      :ets.new(:fast_cars_cache, [:duplicate_bag, :public, :named_table])
      Enum.each(main(), fn element -> :ets.insert(:fast_cars_cache, element) end)
    end
  end


end
iex(1)> Foo.update_ETS_table
:ok
iex(2)> :ets.lookup(:fast_cars_cache, "Koenigsegg")
[
  {"Koenigsegg", %{color: "Blue", mileage: 250.762}},
  {"Koenigsegg", %{color: "Cobalt", mileage: 1297.76}},
  {"Koenigsegg", %{color: "Titanium", mileage: 5360.336}}
]
iex(3)> :ets.lookup(:fast_cars_cache, "Ferrari")
[
  {"Ferrari", %{color: "Blue", mileage: 120012.481}},
  {"Ferrari", %{color: "Red", mileage: 29831.021}},
  {"Ferrari", %{color: "Black", mileage: 24030.674}},
  {"Ferrari", %{color: "Cobalt", mileage: 412.811}}
]
2 Likes