vectorrusthashsetborrowing

How do I convert a HashSet of Strings into a Vector?


I'm trying to convert a HashSet<String> into a sorted vector that can then be joined with commas:

use std::collections::HashSet;

fn main() {
    let mut hs = HashSet::<String>::new();
    hs.insert(String::from("fee"));
    hs.insert(String::from("fie"));
    hs.insert(String::from("foo"));
    hs.insert(String::from("fum"));

    let mut v: Vec<&String> = hs.iter().collect();
    v.sort();

    println!("{}", v.join(", "));
}

This will not compile:

error[E0599]: no method named `join` found for struct `std::vec::Vec<&std::string::String>` in the current scope
  --> src/main.rs:13:22
   |
13 |     println!("{}", v.join(", "));
   |                      ^^^^ method not found in `std::vec::Vec<&std::string::String>`

I understand why I can't join the Vec<&String>, but how can I convert the HashSet to a Vec<String> instead, so it can be joined?

The examples given in What's an idiomatic way to print an iterator separated by spaces in Rust? do not seem to apply because the iterator for Args returns String values, unlike the iterator for HashSet which returns &String.


Solution

  • I encourage you to re-read The Rust Programming Language, specifically the chapter on iterators. Next, become familiar with the methods of Iterator.

    The normal way I'd expect to see this implemented is to convert the HashSet to an iterator and then collect the iterator to a Vec:

    let mut v: Vec<_> = hs.into_iter().collect();
    

    In this case, I'd prefer to use FromIterator directly (the same trait that powers collect):

    let mut v = Vec::from_iter(hs);
    

    Focusing on your larger problem, use a BTreeSet instead, coupled with What's an idiomatic way to print an iterator separated by spaces in Rust?

    use itertools::Itertools; // 0.10.1
    use std::collections::BTreeSet;
    
    fn main() {
        // Create the set somehow
        let hs: BTreeSet<_> = ["fee", "fie", "foo", "fum"]
            .into_iter()
            .map(String::from)
            .collect();
    
        println!("{}", hs.iter().format(", "));
    }