在 Rust 中处理列表 + 分隔符的最佳代码模式

Yur*_*rik 5 rust

这是一个微不足道的 Rust 自行车脱落问题,但我一直看到它以次优(冗长)的方式实现,我想知道 stdlib 是否应该有所帮助,或者是否有一个好的模式?

目标:

  • 每个元素处理代码只能编写一次
  • 如果可能的话,有一种简单的方法来编写“分隔符”处理代码,而无需附加状态(即没有布尔标志)

假设的理想代码——是否值得从 Rust stdlib 请求它或至少将其添加到 itertools(参见问题)?

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!(", "),
        }
    );
}
Run Code Online (Sandbox Code Playgroud)

我主要看到这两种方法。由于格式化代码重复或冗长的上下文状态保留,它们不太理想。我的目标是仅使用 stdlib 来完成此操作,而不创建任何复杂的辅助函数。

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}");
    }
}
Run Code Online (Sandbox Code Playgroud)

Jar*_*ith 1

您不需要布尔标志。您可以使用底层迭代器,然后在获取第一个元素后将其余元素传递给循环for(或者.map更实用的样式):

pub fn foo(ls: &[&str]) -> Option<()> {
    // We get an iterator over the items in a slice
    let mut iter = ls.iter();

    // Get the first item. Note that it's
    // an Option, the slice may be empty.
    // If it is this will essentially
    // return early
    let first = iter.next()?;

    // Do something special with the first element
    println!("first: {first}");

    // Loop over the rest
    for item in iter {
        println!("item: {item}");
    }

    // Return an empty option to satisfy the
    // return type
    Some(())
}   

fn main() {
    foo(&vec!["a", "b", "c"]);
}
Run Code Online (Sandbox Code Playgroud)

你可以在操场上看到,没有解释性的注释,它非常简洁。