我将如何进行这样的匹配

时间:2014-06-16 04:08:15

标签: elixir

我有一个函数,它接受一个id / item元组列表的集合,并且应该替换给定的项目以及id和new item。

def update_item(collection, id, new_item) do
  Enum.map(collection, fn
    ({ ^id, _ }) -> { id, new_item }
    (entry) -> entry
  end)
end

此操作因CompileError和消息unbound variable ^id而失败。我怎样才能做到这一点?有没有一个好方法可以做到这一点,还是我应该采取另一种方式?

2 个答案:

答案 0 :(得分:3)

你可以使用警卫:

iex(1)> collection = [a: 1, b: 2, c: 3, b: 4]

iex(2)> id = :b
iex(3)> new_item = 5

iex(4)> Enum.map(collection, fn
          ({coll_id, _ }) when coll_id == id -> { id, new_item }
          (entry) -> entry
        end)
[a: 1, b: 5, c: 3, b: 5]

答案 1 :(得分:2)

使用经典尾递归,您可以像这样定义update_item

def update_item([{ id, _} | t], id, new_item) do
    [{id, new_item} | update_item(t, id, new_item)]
end

def update_item([h | t], id, new_item) do
    [h | update_item(t, id, new_item)]
end

def update_item([], _, _) do
    []
end

update_item([{4, 56}, {1, 44}, {1, 33}, {2, 55}], 1, 23)
# => [{4, 56}, {1, 23}, {1, 23}, {2, 55}]

如果第一个定义的id与输入匹配,则第一个定义替换第一个项目,而第二个定义只是在不替换项目的情况下递归。第三种方法是空列表的停止条件。