Elixir - 通过管道操作员传递部分输出

时间:2017-10-20 13:00:24

标签: elixir

在Elixir中使用管道运算符时,是否可以选择性/特定于从第一个函数传递到第二个函数的输出?

例如,我正在分三个步骤处理地图 - 我需要删除两个键,更新另一个键的值,最后弹出另一个键,我需要在我的代码中稍后使用它的值。以下是我理想能够实现的目标:

for r <- records do
  {scope, record} = 
    Map.drop(r, [:__struct__, :__meta__])
    |> Map.get_and_update(:id, fn current_value -> 
      {current_value, String.replace(current_value, "join", "scope", global: false)}
    end)
    |> Map.pop(:user_id)

  # SOME OTHER STUFF...

end

这样就可以删除:__struct__:__meta__键,通过将“join”替换为“scope”来更新:id键的值,然后弹出{ {1}}关闭,留下:user_id,其中{scope, record}是弹出键的值,scope是修改后的地图。当然,代码不起作用。

以下是一段示例数据:

record

此过程的第一步有效,因为records = [ %{__struct__: "foo", __meta__: "bar", id: "resource_join:1234", user_id: "user:1234"}, %{__struct__: "foo", __meta__: "bar", id: "resources_join:5678", user_id: "user:5678"}, ] 只返回修改后的地图,这是drop/2的第一个参数的正确输入。但是,get_and_update/3返回一个元组,其中第一个值是函数替换的值,第二个值是修改后的映射。这是管道链失败的地方,因为get_and_update/3期望一个地图作为第一个参数,并且它在这里接收一个元组。

有没有办法可以控制pop/2的输出,以便只返回元组中的第二个值通过管道传递给get_and_update/3?我已经能够通过将这个链条分成几个部分来获得我需要的输出,但是如果它们完全可以将这些链接在一起,我愿意。

1 个答案:

答案 0 :(得分:1)

由于您要丢弃元组的第一个元素并仅将第二个元素传递给Map.pop,因此您可以将|> elem(1)添加到管道中:

|> Map.get_and_update(:id, fn current_value -> 
  {current_value, String.replace(current_value, "join", "scope", global: false)}
end)
|> elem(1)
|> Map.pop(:user_id)

此外,Map.get_and_update + elem(1)只能替换为Map.update,而不会返回密钥的旧值:

|> Map.update(fn current_value -> 
  String.replace(current_value, "join", "scope", global: false)
end)
|> Map.pop(:user_id)