.zip() and .collect() are saying that a vector of floats is not an iterator - trying to zip two vectors into a HashMap

I'm working with The Book and doing the exercises on HashMaps.

These are the errors I'm getting, which are are throwing me off because I know the vector can use the .iter() method.

error[E0277]: `&std::slice::Iter<'_, {float}>` is not an iterator
  --> src\main.rs:29:49
   |
29 |     let v_modes: HashMap<_, _> = &v_keys.iter().zip(&v.iter()).collect();
   |                                                 ^^^ `&std::slice::Iter<'_, {float}>` is not an iterator
   |
   = help: the trait `std::iter::Iterator` is not implemented for `&std::slice::Iter<'_, {float}>`
   = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&std::slice::Iter<'_, {float}>`

error[E0599]: no method named `collect` found for type `std::iter::Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {float}>>` in the current scope
  --> src\main.rs:29:64
   |
29 |     let v_modes: HashMap<_, _> = &v_keys.iter().zip(&v.iter()).collect();
   |                                                                ^^^^^^^
   |
   = note: the method `collect` exists but the following trait bounds were not satisfied:
           `std::iter::Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {float}>> : std::iter::Iterator`
           `&mut std::iter::Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {float}>> : std::iter::Iterator`

Here is the code I'm writing, trying to finish up the last part of the exercise. The problem is in the let v_modes section.

/*
Given a list of integers, use a vector and return the mean (the average value),
median (when sorted, the value in the middle position), and mode
(the value that occurs most often; a hash map will be helpful here) of the list.
*/

fn main() {
    use std::collections::HashMap;

    let mut v = vec![32.0, 45.0, 23.0, 65.0, 12.0, 87.0, 99.0, 33.0, 78.0];
    let mut v_keys = Vec::new();

    {
        let mut a = 0;
        for i in &v {
            a += 1;
            v_keys.push(a - 1);
        }
    }

    dbg!(&v_keys);

    let v_sorted = &v.sort_by(|a, b| a.partial_cmp(b).unwrap());
    let v_len = v.len() as f64;
    let v_mid: usize = v.len() as usize / 2;
    let v_sorted = &v.sort_by(|a, b| a.partial_cmp(b).unwrap());
    let v_len = v.len() as f64;
    let v_mid: usize = v.len() as usize / 2;
    let v_modes: HashMap<_, _> = &v_keys.iter().zip(&v.iter()).collect();
    let v_median = &v[v_mid as usize];
    let mut sum = 0.0;

    for i in &v {
        println!("{}", i);
    }

    for i in &v {
        sum += i;
        println!("{}", &sum);
    }

    let mean = &sum / &v_len;

    dbg!(&v_mid);
    dbg!(&v.len());
    dbg!(&v_len);
    println!("resorted v as {:?}", v_sorted);
    println!("v has {:.1} items", &v_len);
    println!("all the items in v = {:.1}", &sum);
    println!("mean value of all items in v is {:.1}", mean);
    println!(
        "median of v values is {:.1}, it is number {} in the index",
        v_median, v_mid
    );
}

Don't take a reference to the iterator or any temporaries, like after a collect.

1 Like

You can do this:

Note that you don't rake a reference to everything, just where you need it. Also an immutable reference to an iterator is useless.

/*
Given a list of integers, use a vector and return the mean (the average value),
median (when sorted, the value in the middle position), and mode
(the value that occurs most often; a hash map will be helpful here) of the list.
*/

fn main() {
    use std::collections::HashMap;

    let mut v = vec![32.0, 45.0, 23.0, 65.0, 12.0, 87.0, 99.0, 33.0, 78.0];
    let mut v_keys = Vec::new();

    {
        let mut a = 0;
        for i in &v {
            a += 1;
            v_keys.push(a - 1);
        }
    }

    dbg!(&v_keys);

    v.sort_by(|a, b| a.partial_cmp(b).unwrap());
    let v_len = v.len() as f64;
    let v_mid: usize = v.len() as usize / 2;
    v.sort_by(|a, b| a.partial_cmp(b).unwrap());
    let v_len = v.len() as f64;
    let v_mid: usize = v.len() as usize / 2;
    let v_modes: HashMap<_, _> = v_keys.iter().zip(v.iter()).collect();
    let v_median = v[v_mid as usize];
    let mut sum = 0.0;

    for i in &v {
        println!("{}", i);
    }

    for i in &v {
        sum += i;
        println!("{}", sum);
    }

    let mean = sum / v_len;

    dbg!(&v_mid);
    dbg!(&v.len());
    dbg!(&v_len);
    println!("resorted v as {:?}", v_sorted);
    println!("v has {:.1} items", v_len);
    println!("all the items in v = {:.1}", sum);
    println!("mean value of all items in v is {:.1}", mean);
    println!(
        "median of v values is {:.1}, it is number {} in the index",
        v_median, v_mid
    );
}
2 Likes

Watch out for sigils in your error messages

error[E0277]: `&std::slice::Iter<'_, {float}>` is not an iterator

The important part there is the &: Iter is an iterator and &mut Iter is an iterator, but &Iter isn't.

1 Like

Thanks for improving my code, makes better sense now. It looks like I went overboard with "&" references.

That helps a lot. This is the main thing I've been misunderstanding. Thanks for explaining so concisely.