Reputation: 4616
I am new to Rust and recently started learning. I wrote a simple program which does the following.
use std::io;
use std::env;
use std::collections::HashMap;
use std::fs;
fn main() {
let path = env::args().nth(1).unwrap();
let contents = read_file(path);
let map = count_words(contents);
print(map);
}
fn read_file(path: String) -> (String){
let contents = fs::read_to_string(path).unwrap();
return contents;
}
fn count_words(contents: String) -> (HashMap<String, i32>){
let split = contents.split(&[' ', '\n'][..]);
let mut map = HashMap::new();
for w in split{
if map.get(w) == None{
map.insert(w.to_owned(), 1);
}
let count = map.get(w);
map.insert(w.to_owned(), count + 1); // error here
}
return map;
}
fn print(map: HashMap<String, i32>){
println!("Occurences..");
for (key, value) in map.iter() {
println!("{key}: {value}");
}
}
I am able to read the file and add the words into a HashMap and print. However, while trying to add or increment, I get below error.
error[E0369]: cannot add
{integer}
toOption<&{integer}>
--> src\main.rs:27:40 | 27 | map.insert(w.to_owned(), count + 1); | ----- ^ - {integer} |
| | Option<&{integer}>
I know this approach should work in other languages like Java, C# etc. but unsure about how it should work in Rust.
Upvotes: 3
Views: 7862
Reputation: 384
In this block:
if map.get(w) == None{
map.insert(w.to_owned(), 1);
}
let count = map.get(w);
map.insert(w.to_owned(), count + 1); // error here
map.get(w)
gives you an Option<w>
(doc);
You seem to know this to some extent, as you check if it's a None
earlier - the other possibility is that it is what you want - a Some(w)
(not just w
);
You cannot add an int
to a Some
, as the compiler tells you - you have to take "the w
" (the count integer) out of the Some
.
You can unwrap
(doc), though it is not advisable.
You can use pattern matching:
match map.get(&w) {
Some(count) => { map.insert(w, count + 1); }
None => { map.insert(w, 1); }
}
Or, written differently:
if let Some(count) = map.get(&w) {
map.insert(w, count + 1);
} else {
map.insert(w, 1);
};
Or, better yet, you can use the Entry API, which turns it into a simple one liner:
*map.entry(w.to_owned()).or_default() += 1;
Upvotes: 11