我想构建一个计算元素出现在数组中的次数的函数,但是我无法解决编译时错误,这是我的代码
fn vec_count_elem(vec: Vec<int>) -> Vec<int> {
let mut counts: HashMap<int, int> = HashMap::new();;
let mut result: Vec<int>;
for el in vec.iter() {
match counts.find(el) {
Some(count) => {
let new_count: int = count + 1;
counts.remove(el);
counts.insert(*el, new_count)
},
None => counts.insert(*el, 0)
}
}
for value in counts.values() {
result.push(*value);
}
return result;
}
这是编译日志
/sorting/src/main.rs:40:9: 47:10 error: mismatched types: expected `()`, found `bool` (expected (), found bool)
/sorting/src/main.rs:40 match counts.find(el) {
/sorting/src/main.rs:41 Some(count) => {
/sorting/src/main.rs:42 let new_count: int = count + 1;
/sorting/src/main.rs:43 counts.remove(el);
/sorting/src/main.rs:44 counts.insert(*el, new_count)
/sorting/src/main.rs:45 },
查看此示例(http://doc.rust-lang.org/std/collections/struct.HashMap.html#example),counts.find(el)应返回匹配运算符的正确数据类型
谢谢!
UPDATE1:
第一个问题已解决(缺少;
),谢谢Arjan!
现在我的问题在于我在match子句中访问计数hashmap,我收到了这个错误:
sorting/src/main.rs:50:21: 50:27 error: cannot borrow `counts` as mutable because it is also borrowed as immutable
sorting/src/main.rs:50 counts.remove(el);
^~~~~~
sorting/src/main.rs:46:20: 46:26 note: previous borrow of `counts` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `counts` until the borrow ends
任何想法最好的方法是什么?
答案 0 :(得分:4)
使用HashMap的.entry()
方法,你可以制作一个非常紧凑的版本:
use std::collections::hashmap::{HashMap, Occupied, Vacant};
fn vec_count_elem(vec: Vec<int>) -> Vec<int> {
let mut counts: HashMap<int, int> = HashMap::new();
for el in vec.iter() {
match counts.entry(*el) {
Occupied(mut e) => { *e.get_mut() += 1; },
Vacant(mut e) => { e.set(1); }
}
}
return counts.values().map(|i| *i).collect();
}
答案 1 :(得分:1)
此处的问题是,您从bool
返回match
,for
期待()
类型的表达式。您可以通过在匹配后添加;
来解决此问题:
for el in vec.iter() {
match counts.find(el) {
// ...
};
}
但是一旦你解决了这个问题,你的代码还有其他问题:
remove
,因为counts
find
要解决第二个问题,请将find
替换为find_mut
。不幸的是,在None
的情况下,insertnig目前无效,但未来可能会发生变化:
for el in vec.iter() {
let found = match counts.find_mut(el) {
Some(count) => {
*count = *count + 1;
true
}
None => false
};
if !found {
counts.insert(*el, 0);
}
}
无需重新构建代码的简单解决方案就是将find
替换为find_copy
。
答案 2 :(得分:0)
你可以在match
语句之后完成这项工作,因为借用的计数会像这样被释放:
fn vec_count_elem(vec: Vec<int>) -> Vec<int> {
let mut counts: HashMap<int, int> = HashMap::new();;
let mut result: Vec<int> = vec![];
for el in vec.iter() {
let (el, new_count) = match counts.find(el) {
Some(count) => {
let new_count: int = count + 1;
(*el, new_count)
},
None => (*el, 0),
};
counts.remove(&el);
counts.insert(el, new_count);
}
for value in counts.values() {
result.push(*value);
}
result
}
也应首先初始化结果。