Rust中将HashMap转换为字符串时的字符串拼接写法优化问题
问题描述
我尝试将HashMap转换为String类型,要求每个元素之间使用,分隔,单个键值对按照key:value的格式表示。
例如给定如下HashMap:
HashMap::from([ (1, 5), (2, 10), (3, 20), ]);
需要转换得到的目标字符串为:
3:20,2:10,1:5
我目前编写的代码可以正常运行,但map闭包中使用的字符串拼接写法非常怪异,我也不理解为什么拼接时第一个元素需要调用.to_owned(),最后一个元素需要调用.as_str()。
.map(|(k, v)| String::from(k.to_string().to_owned() + ":" + v.to_string().as_str()) )
请问有没有更合理优雅的写法来实现该需求?当前完整代码如下:
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); }
解答
先解释你原来的写法为什么别扭:
Rust 中用+做字符串拼接有固定规则:运算符左边必须是持有所有权的String类型,右边必须是字符串切片&str类型。这是+对应的Add trait 实现决定的——这个方法会接管左侧字符串的所有权,直接在原有内存空间上追加右侧内容,减少内存分配,签名等价于fn add(self, s: &str) -> String,拼接完成后直接返回新的String。
你原来的代码里有不少冗余操作:
k.to_string()本身已经返回String类型,后面跟着的.to_owned()完全多余v.to_string()返回的是String,不符合+右侧参数的类型要求,所以你加了.as_str()转切片,实际上这里直接写&v.to_string()就会自动强转为&str,不需要手动调用转换方法- 最外层包裹的
String::from()也是多余的,+运算本身就返回拼接完成的String,不需要再做一次转换
推荐写法
写法1:用format!宏,可读性最高
不需要记忆任何字符串拼接的类型规则,写法直观,不容易写错:
.map(|(k, v)| format!("{k}:{v}"))
修改后的完整代码:
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); }
写法2:用原生+拼接,性能更优
如果对运行时性能有要求,想避免format!的少量解析开销,可以简化原来的+拼接写法,去掉所有冗余调用:
.map(|(k, v)| k.to_string() + ":" + &v.to_string())
注意:Rust中
HashMap本身是无序的,如果你需要固定输出顺序(比如你示例里按key降序输出3:20,2:10,1:5),需要在拼接前对迭代器做排序处理,否则不同编译版本、不同运行环境下的输出顺序可能不一致。
内容的提问来源于stack exchange,提问作者gameveloster
相关产品推荐
相关产品推荐

