Collecting from HashSet to Vector

I'm fairly new to Rust and have been running into an issue with something I think should be simple so I'm likely doing something wrong.

I'm basically converting from &mut Vec to a HashSet back to a vector. Here's a sample of the code

fn remove_duplicates(nums: &mut Vec<i32>) -> i32 

 let x = HashSet::from_iter(nums).iter().collect::<Vec<i32>>();

And the error is :

|     let x = HashSet::from_iter(nums).iter().collect::<Vec<i32>>();
   |                                             ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=&&mut i32>`
   |
   = help: the trait `FromIterator<&&mut i32>` is not implemented for `Vec<i32>`

Any idea if this is even possible or how I could go about mapping a HashSet to a Vector?

You've created a HashSet<&mut i32>, and then you've created a borrowed iterator on it.

HashSet::from_iter(nums).iter().collect::<Vec<i32>>();
                   ^^^^  ^^^^
                   |     |
                   |     `iter()` is the "borrowed iterator" function, so
                   |     Iterator::Item = &T where T = &mut i32
                   |
                   <&mut Vec<i32> as IntoIterator>::Item = &mut i32

To fix this, use into_iter() (the "owned iterator" function), and also take copies of the items.

let x = HashSet::from_iter(nums.iter().copied()).into_iter().collect::<Vec<i32>>();

Alternatively, you can drain the Vec, instead of taking a copy of the items.

1 Like

Thanks for the explanation. I think I get what happened there. I'll need to refresh my memory on the concept of borrowing in Rust to make sure.

With the changes however I now have

    let x = HashSet::from_iter(nums.iter().copied())
        .into_iter()
        .collect::<Vec<i32>>();
77 |     let x = HashSet::from_iter(nums.iter().copied())
   |             ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `S` declared on the struct `HashSet`

I'm guessing I need to break it up and make the HashSet declaration explicit and then take the vector from that

You've ran into a shortcoming around default type parameter fallback. You can work around it by using

    HashSet::<_>::from_iter(nums.iter().copied())
        .into_iter()
        .collect::<Vec<i32>>();

(You can replace Vec<i32> with Vec<_> too, which is common when collecting -- rustc can usually figure out what's being iterated and just needs the container type.)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.