一个微不足道的Rust自行车着色问题,但我一直看到它以次优(冗长)的方式实现,我想知道stdlib是否应该有所帮助,或者是否有一个好的模式?
目标:
- 每个元素处理代码应该只写一次
- 有一个简单的方法来编写“分隔符”处理代码,而无需额外的状态(即,没有bool标志)
假设理想的代码--是否值得从Rust stdlib请求它,或者至少将它添加到itertools(参见issue)?
fn print_functional(items: &[&str]) {
items.foreach_with_separator(
|elem| {
// some arbitrary complex item handling, not printing
print!("{elem}");
},
|| {
// some arbitrary complex "separator" handling
print!(", "),
}
);
}
我主要看到这两种方法。由于格式化代码重复或冗长的上下文状态保持,它们不太理想。我的目标是只使用stdlib,而不创建任何复杂的helper函数。
fn main() {
let items = vec!["foo", "bar", "baz"];
print_with_var(&items);
print_split_last(&items);
}
fn print_with_var(items: &[&str]) {
let mut first_printed = false;
for elem in elems {
if first_printed {
print!(", ");
} else {
first_printed = true;
}
// this represents some multi-line processing,
// but for this example I'm keeping it simple
let formatted_value = elem.to_string();
print!("{formatted_value}");
}
}
fn print_split_last(items: &[&str]) {
if let Some((last, elems)) = items.split_last() {
for elem in elems {
// this is sub-optimal because elem formatting is duplicated
let formatted_value = elem.to_string();
print!("{formatted_value}, ");
}
let formatted_value = last.to_string();
print!("{formatted_value}");
}
}
6条答案
按热度按时间gfttwv5a1#
一个 DRY 解决方案是使用peekable iterators:
https://godbolt.org/z/zMaP5oExa
0ejtzxu12#
另一种itertools方法,通过使用intersperse避免了join中的字符串分配:
Demo
Rust nightly甚至将
intersperse
添加到std本身,这将更加出色。zynd9foi3#
你不需要一个布尔标志。你可以使用底层的迭代器,然后在抓取第一个元素后,将其余的元素传递给
for
循环(或者.map
它以获得更多的函数式风格):你可以看到playground没有解释性注解,它非常简洁。
cpjpxq1n4#
创建另一个函数是最简单的方法。
如果涉及到很多状态,可以将其设为闭包并捕获状态。
你甚至可以把闭包作为一个参数。为了避免创建临时字符串,您应该转换为实现
Display
的类型。mkshixfv5#
使用Itertools或不介意依赖关系的人有
itertools::join
:Demo
或更多定制:
Demo
xcitsw886#
最简单的,不使用板条箱的方法是:
很清楚如何将其扩展到
,
以外的分隔符。