King Natsu
King Natsu

Reputation: 463

Pattern match against the other element of a map

I just want to know if there's a clean way to get the "other" element from a map in Elixir. By "other" I mean a second key-value pair, whose key I don't know.

Example: %{success: boolean, other => value}

This is the best I could come up with:

case map do
  %{success: true} -> 
     other = map |> Map.delete(:success) |> Map.values |> List.first 
     # Do something with other
  %{success: false} -> 
     error = map |> Map.delete(:success) |> Map.values |> List.first 
     # Do something with error
end

Upvotes: 0

Views: 805

Answers (3)

7stud
7stud

Reputation: 48599

iex(9)>  map = %{:success => true, {1,2,3} => 10}
%{:success => true, {1, 2, 3} => 10}

iex(10)> List.first(for {key, val} <- map, key != :success, do: val) 
10

Upvotes: 0

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

I would go with old good Enum.reduce/3:

Enum.reduce %{success: true, foo: 42}, %{state: nil, map: %{}}, fn
  {:success, value}, acc -> %{acc | state: value}
  {key, value}, acc -> %{acc | map: Map.put(acc.map, key, value)}
end
#⇒ %{map: %{foo: 42}, state: true}

Now you might do whatever is needed without code duplication. Actually, the tuple is fine for collecting the result:

{success, map} =
  Enum.reduce %{success: true, foo: 42}, {nil, %{}}, fn
    {:success, value}, {_, acc} -> {value, acc}
    {key, value}, {state, acc} -> {state, Map.put(acc, key, value)}
  end
#⇒ {true, %{foo: 42}}

Upvotes: 1

Igor Drozdov
Igor Drozdov

Reputation: 15045

There's Map.pop/3 function, which accepts map and a key and returns a tuple with the value and a map without the key:

Map.pop %{ a: 1, b: 2 }, :a
# => {1, %{b: 2}}

and will refactor your code into something like:

case Map.pop(map, :success) do
  {true, other_map} -> 
     other = other_map |> Map.values |> List.first 
     # Do something with other
  {false, other_map} -> 
     error = other_map |> Map.values |> List.first 
     # Do something with error
end

Upvotes: 2

Related Questions