Symbol counting


#1

Hello again… I need to find an entry for each character in the string, but rustc gives error. What’s wrong?

use std::collections::HashMap;

fn scounter(s: &str) -> HashMap<char, usize> {
let mut map: HashMap<char, usize> = HashMap::new();

for (i, c) in s.char_indices() {
	match map.get_mut(&c) {
		Some(x) => *x+=1,
		None => map.insert(c, 1)
	}
}
return map;
}

fn main() {
let x = "Hello!";
println!("{:?}", scounter(x));
}

Errors:
main.rs:7:3: 10:4 error: match arms have incompatible types:
expected (),
found core::option::Option<usize>
(expected (),
found enum core::option::Option) [E0308]
main.rs: 7 match map.get_mut(&c) {
main.rs: 8 Some(x) => *x+=1,
main.rs: 9 None => map.insert(c, 1)
main.rs:10 }
main.rs:7:3: 10:4 help: run rustc --explain E0308 to see a detailed explanation
main.rs:9:12: 9:28 note: match arm with an incompatible type
main.rs:9 None => map.insert(c, 1)
^~~~~~~~~~~~~~~~


#2

As the error mentions:

error: match arms have incompatible types:

One arm is returning (), and one is returning Option<usize>.

You should be able to use ; to make them both return ():

        Some(x) => { *x+=1; },
        None => { map.insert(c, 1); },

However, this introduces a new error:

 <anon>:9:13: 9:16 error: cannot borrow `map` as mutable more than once at a time [E0499]
<anon>:9 		None => { map.insert(c, 1); },
         		          ^~~

The entry() API was designed to make this case easy: http://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.entry


#3

Excuse me. I did not quite understand. Can I see a working version of my code please?


#4

With entry API it will look like this


use std::collections::HashMap;

fn scounter(s: &str) -> HashMap<char, usize> {
    let mut map: HashMap<char, usize> = HashMap::new();

    for (i, c) in s.char_indices() {
            *map.entry(c).or_insert(0) +=1;
        }
        return map;
}


#5

Thanks! Now I understand.