更新结构列表的最佳方法

Iag*_*íaz 3 elixir

假设我有一个结构体列表id,其键之一为:

users = [
  %User{id: 1, attempts: 5},
  %User{id: 2, attempts: 12},
  %User{id: 3, attempts: 2}
]
Run Code Online (Sandbox Code Playgroud)

什么是将尝试次数更新为99个用户的最佳方法(最灵丹妙药的方法),id == 2以获取新的用户列表:

updated_users = [
  %User{id: 1, attempts: 5},
  %User{id: 2, attempts: 99},
  %User{id: 3, attempts: 2}
]
Run Code Online (Sandbox Code Playgroud)

感谢您的帮助!

Koz*_*łek 5

Enum.map(users, fn
  %User{id: 2} = user -> %User{user | attempts: 99}
  user -> user
end)
Run Code Online (Sandbox Code Playgroud)

您可以将其封装到某个模块中,并给它一个好名字:)


Ale*_*kin 5

可以说,最灵丹妙药的方法是使用Access行为和Kernel.put_in/3

\n\n
put_in users,\n  [Access.filter(&match?(%User{id: 2}, &1)), \n   Access.key(:attempts)],\n  99\n#\xe2\x87\x92 [\n#  %User{attempts: 5, id: 1},\n#  %User{attempts: 99, id: 2},\n#  %User{attempts: 2, id: 3}\n#]\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

通过更改过滤器功能,这可以轻松扩展以更新多个元素。

\n

  • @丹尼尔,我不觉得很难读,但无论如何。是的,使用它而不是 `Enum.map/2` 是有原因的:它适用于任何深度,而 `map` 仅当结构是顶级可枚举的直接子级时才有效。习惯在任何地方使用“Access”是有意义的,这样a)可以轻松阅读它,b)当涉及到深度嵌套的术语时,不要发明复杂的“map”/“reduce”怪物。“访问”方法赋予了令人难以置信的灵活性。 (2认同)