Tip to handle edge cases in iter

Suppose I have something iterate.able like a vector

let vec = vec![1, 2, 3];

and I want to, say, print it to get {1|2|3}... Now iterating through the vector as in

println!("{")
for in vec.iter() {
println!("{:?}|",x);
}
println!("}");

doesn't work because of the edge case with the last element. Is there a clever trick to handle this "efficiently" without much branching?

Of course many types implement a pretty printer like '{:#?}', but this question is more about how to implement this in general.

You can convert Vec<i32> to Vec<String> and then use the join method.

fn main() {
    let v = vec![1, 2 , 3];
    let s: Vec<String> = v.iter().map(|x| x.to_string()).collect();
    println!("{{{:}}}", s.join("|"));
}

Here's the first general-purpose way that came to mind:

fn main() {
    let v = vec![1, 2, 3];
    let mut iter = v.iter().peekable();

    print!("{{");
    while let Some(x) = iter.next() {
        match iter.peek() {
            Some(_) => print!("{:?}|", x),
            None => print!("{:?}", x),
        }
    }
    println!("}}");
}

Probably not super efficient, as it introduces a branch for every element in the vec. (unless the optimizer is more clever than I thought...)

How about this?

print!("{")
let mut iter = vec.iter();
if let Some(first) = iter.next() {
    print!("{:?}", first);
    for x in iter {
        print!("|{:?}", x);
    }
}
println!("}");
3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.