Лучший способ обновить список структур - PullRequest
3 голосов
/ 20 октября 2019

Допустим, у меня есть список структур, с id в качестве одного из его ключей:

users = [
  %User{id: 1, attempts: 5},
  %User{id: 2, attempts: 12},
  %User{id: 3, attempts: 2}
]

Каков наилучший способ (самый эликсирный способ) для обновления количества попыток99 для пользователя с id == 2, чтобы получить новый список пользователей:

updated_users = [
  %User{id: 1, attempts: 5},
  %User{id: 2, attempts: 99},
  %User{id: 3, attempts: 2}
]

Спасибо за помощь!

Ответы [ 3 ]

5 голосов
/ 20 октября 2019
Enum.map(users, fn
  %User{id: 2} = user -> %User{user | attempts: 99}
  user -> user
end)

Вы можете инкапсулировать его в некоторый модуль и дать ему хорошее имя:)

3 голосов
/ 21 октября 2019

Возможно, наиболее эликсирным подходом будет использование Access поведения и Kernel.put_in/3:

put_in users,
  [Access.filter(&match?(%User{id: 2}, &1)), 
   Access.key(:attempts)],
  99
#⇒ [
#  %User{attempts: 5, id: 1},
#  %User{attempts: 99, id: 2},
#  %User{attempts: 2, id: 3}
#]

Это может быть легко расширенообновить несколько элементов, изменив функцию фильтра.

0 голосов
/ 21 октября 2019

Если вы делаете много обновлений, вероятно, лучше всего построить карту, чтобы вам не приходилось повторять список для каждого обновления.

[
  %User{attempts: 5, id: 1},
  %User{attempts: 12, id: 2},
  %User{attempts: 2, id: 3}
]
|> Map.new(fn user -> {user.id, user} end)
|> Map.update!(2, &%User{&1 | attempts: 99})
|> Map.values()

Вы можете сделать столько же, сколько Map.update!/3 звонки по мере необходимости, для обновления разных идентификаторов.

...