Reputation: 61
I've been doing exercises after Rust Books's Chapter 8. I've implemented the first task, but there is a problem: I don't change the function and the input, but the result is always different.
use std::collections::HashMap;
fn main() {
println!("{:?}",vector(&mut vec![10,15,20,20]));
println!("{:?}",vector(&mut vec![10,15,20,20]));
println!("{:?}",vector(&mut vec![10,15,20,20]));
println!("{:?}",vector(&mut vec![10,15,20,20]));
}
fn vector(V:&mut Vec<i32>)->[i32;3]{
let average:i32 = V.iter().sum::<i32>()/(V.len() as i32);
V.sort();
let median:i32 = V[V.len()/2+1];
let mut map = HashMap::new();
let mut mode = 0;
for el in V{
let count = map.entry(el).or_insert(0);
//or_insert returns reference to the value of the key
*count+=1; //dereference and increase;
}
for (k,v) in map{
if v>mode{
mode=*k;
}
}
return [average,median,mode]
}
The outputs vary from execution to execution:
[16, 20, 20]
[16, 20, 15]
[16, 20, 15]
[16, 20, 20]
Here's a playground runnable example
Why does the output differ from the same input values?
Upvotes: 1
Views: 117
Reputation: 161457
The fact that you assign *k
to mode
does not make sense, did you mean to assign v
? It seems like at a minimum this needs to be:
let mut mode = (0, 0);
for (k, v) in map {
if v > mode.1 {
mode = (*k, v);
}
}
return [average, median, mode.0];
The reason your code is behaving non-deterministically is because hashmaps do not make any guarantees about the order in which the key/value pairs are produced by the iterator. On the docs page you mentioned for instance, it notes
This code will print each pair in an arbitrary order:
and because your code as-is uses v
instead of *k
for the first check (and v
is a small value compared to *k
, the first value to be produced by the hashmap will a always be set as the mode
value because the the first entry is larger than the default 0
mode, and then future pairs are never large enough to change it.
Upvotes: 3