Reputation: 11
I have a HashMap with key = id, value = Status; Now I want to update the status, but I have to remove and insert, because the new status is created from the old status. Is there any way to update without remove and insert?
enum Status {
InCompleted(HashSet<WorkerId>),
Working(WorkerId, HashSet<WorkerId>),
Completed,
}
impl Status {
fn to_working(self, worker_id: WorkerId) -> Self {
match self {
Self::InCompleted(w) => Self::Working(worker_id, w),
_ => self,
}
}
// remove and insert new
let old_status = h.remove(&id).unwrap();
h.insert(id, old_status.to_working(cur_worker));
Upvotes: 1
Views: 2390
Reputation: 1801
Check out the entry
method for HashMap
, and its and_modify
method: https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.and_modify.
You can have something like:
h.entry(&id).and_modify(|status|
*status = status.to_working(cur_worker)
);
Upvotes: 4
Reputation: 70840
This is nothing that is exactly the same, unfortunately, but you can avoid looking up the value twice by replacing with the default, then inserting the new value. Note that it requires T: Default
. If it is not, use a sensible default value (it'll stay there if the transformation will panic)
let status = h.get_mut(&id).unwrap();
let old_status = std::mem::take(status);
*status = old_status.to_working(cur_worker);
You can use a crate like replace_with:
replace_with::replace_with_or_default(
h.get_mut(&id).unwrap(),
|old_status| old_status.to_working(cur_worker),
);
Upvotes: 1