Rust hashmap的向量,查找操作最少



我有一个rust中的hashmap,它的键值是一个字符串的hashset

我想实现一个方法,插入字符串到一个现有的键,如果它不存在,创建一个空条目。

我有下面的代码片段,我真的很喜欢这里只有一次查找

let mut map: HashMap<&str, HashSet<&str>> = HashMap::new();
let park1 = "poneyland";
let horse = "foo";
map.entry(park1)
.or_insert_with(|| HashSet::from([horse]))
.insert(horse);

但是我想让HashSet的最大大小为25。

为此,我尝试了以下

match map.entry(park1){
Entry::Occupied(x) => {
let tmp_entry = x.into_mut();
if tmp_entry.len() < 25 {
Ok(tmp_entry.insert(horse))
}
else{
Err("maximum size reached")
}
}
Entry::Vacant(y) => {
let tmp_hash_set = HashSet::from([horse]);
Err(y.insert(tmp_hash_set))
}
};
}

但是我得到以下错误

22 |   match map.entry(park1){
|   ---------------------- `match` arms have incompatible types
...
25 | /         if tmp_entry.len() < 64{
26 | |             Ok(tmp_entry.insert(horse))
27 | |         }
28 | |         else{
29 | |             Err("maximum size reached")
30 | |         }
| |_________- this is found to be of type `Result<bool, &str>`
...
34 |           Err(y.insert(tmp_hash_set))
|           ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
|
= note: expected enum `Result<bool, &str>`
found enum `Result<_, &mut HashSet<&str>>`

锈操场

更新,根据@Ry评论,我做了以下事情:

let current_size = map.len();
match map.entry(park1){
Entry::Occupied(x) => {
let tmp_entry = x.into_mut();
if tmp_entry.len() < 64{
Ok(tmp_entry.insert(horse))
}
else{
Err("maximum horses reached in park")
}
}
Entry::Vacant(y) => {
if current_size == 9999 {
Err("maximum number of parks reached")
}
else{
let tmp_hash_set = HashSet::from([horse]);
y.insert(tmp_hash_set);
Ok(true)
}
}
};

以上方法有效,我很好奇是否有更好的方法?

以上工作,我很好奇是否有更好的方法?

细微的改进是可能的,尽管主旨似乎是合理的:

您可以解除条件作为匹配保护,这消除了一些块(括号),并使代码更具声明性:

match map.entry(park1) {
Entry::Occupied(x) if x.get().len() < 64 => 
Ok(x.into_mut().insert(horse)),
Entry::Occupied(_) => Err("maximum horses reached in park"),
Entry::Vacant(_) if current_size == 9999 => 
Err("maximum number of parks reached"),
Entry::Vacant(y) => {
let tmp_hash_set = HashSet::from([horse]);
y.insert(tmp_hash_set);
Ok(true)
}
};

你也可以重新组织,比如把两个错误情况都放在上面,这样更清晰,尽管这更像是一种品味:

match map.entry(park1) {
Entry::Occupied(x) if x.get().len() >= 64 =>
Err("maximum horses reached in park"),
Entry::Vacant(_) if current_size == 9999 =>
Err("maximum number of parks reached"),
Entry::Occupied(x) =>
Ok(x.into_mut().insert(horse)),
Entry::Vacant(y) => {
let tmp_hash_set = HashSet::from([horse]);
y.insert(tmp_hash_set);
Ok(true)
}
};

不需要tmp_hash_set:

y.insert(HashSet::from([horse]));
Ok(true)

最新更新