gameveloster
gameveloster

Reputation: 1503

String Concatenation when Creating a String from a HashMap in Rust

I am trying to convert a HashMap to a String where every item is separated by , and a key/value pair is represented using the format key:value.

For example, a HashMap

HashMap::from([
    (1, 5),
    (2, 10),
    (3, 20),
]);

should be converted to the String

3:20,2:10,1:5

My code below appears to work, I am only able to get it to work by using a strange way of concatenating the strings in the closure for map. Also do not understand why the first element needed to use .to_owned() while the last element uses .as_str().

.map(|(k, v)| String::from(k.to_string().to_owned() + ":" + v.to_string().as_str()) )

Is there a better way to write this?

use std::collections::HashMap;

fn main() {
    let foo = HashMap::from([
      (1, 5),
      (2, 10),
      (3, 20),
    ]);
    
    let res = foo
        .iter()
        .map(|(k, v)| String::from(k.to_string().to_owned() + ":" + v.to_string().as_str()) )
        .collect::<Vec<String>>()
        .join(",");
    
    println!("{}", res);
}

Upvotes: 0

Views: 865

Answers (1)

kopecs
kopecs

Reputation: 1731

I would probably use format! here:

use std::collections::HashMap;

fn main() {
    let foo = HashMap::from([
      (1, 5),
      (2, 10),
      (3, 20),
    ]);
    
    let res = foo
        .iter()
        .map(|(k, v)| format!("{}:{}", k, v))
        .collect::<Vec<String>>()
        .join(",");
    
    println!("{}", res);
}

playground


If you really want to avoid unnecessary allocation for the Vec and intermediate Strings (see also this question) you could adopt a slightly different approach and do this with a fold:

use std::collections::HashMap;
use std::fmt::Write;

fn main() {
    let foo = HashMap::from([(1, 5), (2, 10), (3, 20)]);

    let res = foo.iter().fold(String::new(), |mut s, (k, v)| {
        if !s.is_empty() {
            s.push(',');
        }
        
        write!(s, "{}:{}", k, v).expect("write! on a String cannot fail");
        s
    });

    println!("{}", res);
}

playground

Upvotes: 2

Related Questions