Reputation: 3726
When running the following code, which comes from attempting the exercise in the Rust Book:
use std::collections::HashMap;
fn main() {
let mut values = [5, 34, 31, 4, 31, 25, 28, 45, 43, 14];
values.sort();
let mut total = 0;
let mut mode_collection = HashMap::new();
let mut mode = HashMap::new();
for value in values.iter() {
let count = mode_collection.entry(value.clone()).or_insert(0);
*count += 1;
total += value;
};
for (value, count) in mode_collection.iter() {
let count_values = mode.entry(count).or_insert(vec![]);
count_values.push(value.clone());
}
let mut largest_count: i32 = 0;
for count in mode.keys().collect() {
if count > largest_count {
largest_count = count;
}
}
println!("The average of the values is {}", total / values.len());
println!("The median of the values is {}", values[values.len() / 2]);
println!("The mode of the values is {:?}", mode[&largest_count]);
}
I get an error:
error[E0282]: type annotations needed
--> src\main.rs:24:18
|
24 | for count in mode.keys().collect() {
| ^^^^^^^^^^^^^^^^^^^^^ cannot infer type
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.
error: could not compile `enums`
To learn more, run the command again with --verbose.
How can I avoid this error?
As best I can tell, type annotations cannot be added to for
loops. However type annotations are required when using collect()
. When I get rid of collect()
count
is a &&{Integer}
(a double borrowed integer?) so the largest_count
and count
variable can't be compared.
Upvotes: 1
Views: 2000
Reputation: 1637
If you need an explicit type annotation, you can use next semantics:
for count in mode.keys().collect::<Vec<_>>() {
// do stuff over each count
}
You don't need to collect items to iterate over them in for
cycle. mode.keys()
is already an iterator, so you can just write:
for count in mode.keys() {
// do stuff
}
If you need to get some single result from an iterator, it is better to use fold
:
let largest_count = mode.keys().copied().fold(0, |largest, current| largest.max(current));
In your particular case you can just write:
let largets_count = mode.keys().copied().max();
Upvotes: 3
Reputation: 2618
You're running into two issues here:
collect()
fails because it's impossible to know what type the resulting collection should have. You can annotate the type through the turbo-fish as mode.keys().collect::<Vec<_>>()
. This won't fix your issue since it doesn't change the type of the items being collected.**count
turns an &&i32
into an i32
and allows you to compare it as expected.You might also want to rethink storing references to integers in the hashmap, then you could solve the issue with a copied()
call on the keys()
iterator.
Upvotes: 2