Elixir 更新结构列表的最佳方法

Elixir 更新结构列表的最佳方法,elixir,Elixir,假设我有一个结构列表,其中一个键是id: users = [ %User{id: 1, attempts: 5}, %User{id: 2, attempts: 12}, %User{id: 3, attempts: 2} ] 使用id==2将用户的尝试次数更新到99次以获得新用户列表的最佳方法(最有效的方法)是什么: updated_users = [ %User{id: 1, attempts: 5}, %User{id: 2, attempts: 99}, %Us

假设我有一个结构列表,其中一个键是
id

users = [
  %User{id: 1, attempts: 5},
  %User{id: 2, attempts: 12},
  %User{id: 3, attempts: 2}
]
使用
id==2
将用户的尝试次数更新到99次以获得新用户列表的最佳方法(最有效的方法)是什么:

updated_users = [
  %User{id: 1, attempts: 5},
  %User{id: 2, attempts: 99},
  %User{id: 3, attempts: 2}
]
谢谢你的帮助

Enum.map(用户,fn
%用户{id:2}=User->%User{User|尝试次数:99}
用户->用户
(完)

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

如果您正在进行许多更新,最好是构建一个映射,这样您就不必为每次更新迭代列表

[
%用户{尝试次数:5,id:1},
%用户{尝试次数:12,id:2},
%用户{尝试次数:2,id:3}
]
|>Map.new(fn user->{user.id,user}end)
|>地图更新!(2,&%用户{&1}尝试次数:99})
|>Map.values()

您可以根据需要执行任意多个调用,以更新不同的ID。

可以说,最灵丹妙药的方法是使用行为和:

put_在用户中,
[Access.filter(&match?(%User{id:2},&1)),
Access.key(:尝试)],
99
#⇒ [
#%User{尝试次数:5次,id:1},
#%User{尝试次数:99次,id:2},
#%User{尝试次数:2,id:3}
#]


通过更改过滤函数,这可能很容易扩展到更新多个元素。

这很难理解,有什么理由用它代替映射函数吗?@Daniel我不觉得很难理解,但无论如何。是的,使用它而不是
Enum.map/2
是有原因的:它适用于任何深度,而
map
仅在结构是顶级可枚举对象的直接子对象时才有效。习惯于在任何地方使用
Access
都是有意义的,a)容易阅读,b)不要发明复杂的
map
/
减少
怪物,当涉及到深度嵌套的术语时
Access
方法具有难以置信的灵活性。@Daniel也许这个例子会告诉你“为什么
Access
”比一大堆单词更好:是的,我几分钟前就注意到了,我想问题不在于它很难读,而在于它是我第一次看到它。也不是在《入门指南》中,也不是在很多示例中都没有提到这一点,我想唯一的方法就是查看文档。@Daniel或者编写自己的库来广泛处理深度嵌套的结构:)没问题。最好指出,它每次都枚举整个列表O(n),因此如果被多次调用,最好构建一个映射,即O(1)。如果有兴趣,请看我的答案。