【问题标题】:How to determine if a value exists in a map of maps如何确定一个值是否存在于地图的地图中
【发布时间】:2022-01-18 21:06:44
【问题描述】:

我有以下用于表示 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

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

【问题讨论】:

    标签: elixir


    【解决方案1】:

    使用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}
    

    【讨论】:

    • 嵌套的 reduce_while 块看起来很丑,但正是我要求的,谢谢
    • try/throw/catch 是一种更好、更惯用的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 2016-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多