使用Rust hashmaps - .find()不返回match的预期值

时间:2014-10-24 10:31:38

标签: hashmap match rust

我想构建一个计算元素出现在数组中的次数的函数,但是我无法解决编译时错误,这是我的代码

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

任何想法最好的方法是什么?

3 个答案:

答案 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返回matchfor期待()类型的表达式。您可以通过在匹配后添加;来解决此问题:

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   
}

也应首先初始化结果。