如何确定某个值是否存在于地图的地图中

How to determine if a value exists in a map of maps

我有以下用于表示 int/bool 元组矩阵的长生不老药映射。使用地图是可取的,因为我想使用访问行为,例如矩阵[0][3].

matrix = %{
  0 => %{
    0 => {22, false},
    1 => {13, false},
    2 => {17, false},
    3 => {11, false},
    4 => {0, false}
  },
  1 => %{
    0 => {8, false},
    1 => {2, false},
    2 => {23, false},
    3 => {4, false},
    4 => {24, false}
  },
  2 => %{
    0 => {21, false},
    1 => {9, false},
    2 => {14, false},
    3 => {16, false},
    4 => {7, false}
  }
}

我想编写一个函数,它会给出地图中给定数字的行和列,例如

get_position(22) # { 0, 0 }
get_position(16) # { 2, 3 }

我可以使用列表理解来做到这一点,例如

  def get_position (matrix, n) do
    for {i, row} <- matrix, {j, {^n, _}} <- row, do: {i, j}
  end

这是低效的,因为要访问所有值。有没有更有效的方法来做到这一点,即在找到值时停止迭代?

使用Enum.reduce_while/3

Enum.reduce_while(matrix, nil, fn
  {ok, ov}, nil ->
    ov
    |> Enum.reduce_while(nil, fn
      {ik, {22, _}}, nil -> {:halt, {ok, ik}}
      _, _ -> {:cont, nil}
    end)
    |> case do
      nil -> {:cont, nil}
      found -> {:halt, found}
    end
  _, _ -> {:cont, nil}
end)

#⇒ {0, 0}

另一种方法是使用 try/throw/catch

try do
  for {ok, ov} <- matrix, {ik, {iv, _}} <- ov, iv == 16,
    do: throw {ok, ik} 
catch
  e -> e
end

#⇒ {2, 3}