Is there an actual way to insert an element into a HashMap/HashSet so that:
- It does not replace the current value if the key was already present
- It returns if the key was already present in some way or another (bool/Option/Result/etc.)
- It does not do lookup twice
- The provided key is not necessarily of type K but is of type Q such that
K : Borrow<Q> + From<Q> and it only constructs the key (K) from the given lookup key (Q) if it turns out that the key was not yet present and thus now needs to be constructed for insertion
- It can be done in stable Rust
I don't care if it's a single function or a multitude of statements.
I think entry API is what you want - but I'm not sure about your key requirements.
in HashBrown does roughly what you want (although it uses ToOwned, not From).
std does use hashbrown, but does not expose its API.
i do not believe there is anything in std that exposes the API that you want.
if you do want to use the std HashMap, i would recommend doing two lookups
the sandard library hashmap has an .entry() API, which almost meets your requirements, except for 4.
if you are ok with an external crate, you can use hashbrown, which has an entry_ref() api, this API is not exposed in std.
let mut words: HashMap<String, usize> = todo!();
match words.entry_ref("hello") {
EntryRef::Occupied(occupied_entry) => {
println!("key already mapped to value {}", occupied_entry.get());
}
EntryRef::Vacant(vacant_entry_ref) => {
println!("key doesn't exist, allocating key and inserting value...");
vacant_entry_ref.insert(42);
// alternatively, if you don't want to use `ToOwned` to convert the query key
//vacant_entry_ref.insert_with_key(String::from("hello"), 42);
}
}