如何解决如何将 Vec<> 传播到 format!() 的参数中?
我有一个 Vec
字符串(str
或 String
),我想将它们用作 format!()
的参数。如果 JS 的 ...
语法可用,我会这样做:
let data = vec!["A","B","C"];
let result = format!("{} says hello to {} but not to {}",...data);
在 Rust 中是否有任何替代方案可以使这样的事情成为可能,并且理想情况下它不会变得非常冗长?
我认为部分困难在于 Vec
可能没有正确数量的参数,因此如果它有错误的数量,我可以接受它恐慌。
解决方法
如果不手动编写大量代码或使用过程宏来生成必要的代码,目前没有办法做到这一点。
作为更简单的解决方法,您可以尝试使用 dynfmt,它提供了动态传递参数的方法。
use dynfmt::{Format,SimpleCurlyFormat};
let formatted = SimpleCurlyFormat.format("{} says hello to {} but not to {}",&["A","B","C"]);
assert_eq!("A says hello to B but not to C",formatted.expect("formatting failed"));
,
dyn-fmt crate 看起来正是我需要的。它指定了一个特征,它向字符串添加了一个 format()
方法,它接受一个迭代器。任何额外的参数都会被忽略,缺少的参数会被替换为一个空字符串,所以它不会恐慌。如果您不需要 format!()
的各种格式选项,那么它看起来是一个非常好的可靠选项。
use dyn_fmt::AsStrFormatExt;
let data = vec!["A","C"];
let result = "{} says hello to {} but not to {}".format(data);
assert_eq!(result,"A says hello to B but not to C");
,
我认为在@Netwave 的回答中生成 Vec<String>
是一种浪费,所以我使用 iter.flat_map()
对其进行了改进:
fn flat_map_niave(b: &mut Bencher) {
let data = vec!["A","C"];
let separators = vec![" says hello to "," but not to "];
b.iter(|| {
let mut phrases = separators.iter();
data.iter()
.intersperse_with(|| phrases.next().unwrap())
.flat_map(|s| s.chars())
.collect::<String>()
});
}
有多种技巧可以以牺牲可读性为代价来提高性能,我将这些技巧留在 playground 中。
-
flat_map_improved
:使用Vec<u8>
和String::from_utf8()
-
flat_map_unchecked
:使用Vec<u8>
和String::from_utf8_unchecked()
running 4 tests
test flat_map_improved ... bench: 134 ns/iter (+/- 17)
test flat_map_niave ... bench: 145 ns/iter (+/- 9)
test flat_map_unchecked ... bench: 116 ns/iter (+/- 6)
test vec_of_strings ... bench: 235 ns/iter (+/- 6)
,
您不能像在 js
或 python
中那样扩展它们。
但是您可以在 join
或 Vec<String>
上使用 Vec<&str>
:
let data = vec!["A","C"];
let result = data.join("->");
根据 nightly,您可以使用 intersperse_with
和迭代器的组合:
let data = vec!["A","C"];
let phrases = vec![" says hello to "," but not to "];
let mut separators = phrases.iter().map(|x| x.to_string());
let result = data
.iter()
.map(|x| x.to_string())
.intersperse_with(|| separators.next().unwrap())
.collect::<String>();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。