Search code examples
elixirphoenix-framework

Building Options for Select from Elixir Map


Assuming this data_set,

 %{"ACTION" => "avail.datacenters",
"DATA" => [%{"ABBR" => "dallas", "DATACENTERID" => 2,
  "LOCATION" => "Dallas, TX, USA"},
%{"ABBR" => "fremont", "DATACENTERID" => 3,
  "LOCATION" => "Fremont, CA, USA"},
%{"ABBR" => "atlanta", "DATACENTERID" => 4,
  "LOCATION" => "Atlanta, GA, USA"},
%{"ABBR" => "newark", "DATACENTERID" => 6, "LOCATION" => "Newark, NJ, USA"},
%{"ABBR" => "london", "DATACENTERID" => 7,
  "LOCATION" => "London, England, UK"},
%{"ABBR" => "tokyo", "DATACENTERID" => 8, "LOCATION" => "Tokyo, JP"},
%{"ABBR" => "singapore", "DATACENTERID" => 9,
  "LOCATION" => "Singapore, SG"},
%{"ABBR" => "frankfurt", "DATACENTERID" => 10,
  "LOCATION" => "Frankfurt, DE"},
%{"ABBR" => "shinagawa1", "DATACENTERID" => 11,
  "LOCATION" => "Tokyo 2, JP"}], "ERRORARRAY" => []}}

In Ruby, i could do

formatted_array_of_hashes = data_set.each.map{ |h| { h["LOCATION"] => h["DATACENTERID"] }}

and then

merged_hash = Hash[*formatted_array_of_hashes.map(&:to_a).flatten]

... and i would have location,datacenterid to use in a select Tag.

Please how can i achieve something similar in Elixir?

Any Pointers in the right direction would be highly appreciated


Solution

  • You can use for, return a 2-tuple in the do and put it into: %{}:

    map = for %{"LOCATION" => k, "DATACENTERID" => v} <- data_set, into: %{}, do: {k, v}
    

    If you want to use this with Phoenix.HTML.Form.select/4 though, you don't need to build the map. You can pass a list of tuples. That way you won't lose the ordering of the elements like you would with maps since maps are unordered.

    select _, _, for(%{"LOCATION" => k, "DATACENTERID" => v} <- data_set, do: {k, v})
    

    Sidenote: your Ruby code can also be simplified to:

    hash = data_set.map { |h| [h["LOCATION"], h["DATACENTERID"]] }.to_h