Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String join on strings in Vec in reverse order without a `collect`

I'm trying to join strings in a vector into a single string, in reverse from their order in the vector. The following works:

let v = vec!["a".to_string(), "b".to_string(), "c".to_string()];
v.iter().rev().map(|s| s.clone()).collect::<Vec<String>>().connect(".")

However, this ends up creating a temporary vector that I don't actually need. Is it possible to do this without a collect? I see that connect is a StrVector method. Is there nothing for raw iterators?

like image 982
Ray Avatar asked Jan 04 '15 19:01

Ray


2 Answers

I believe this is the shortest you can get:

fn main() {
    let v = vec!["a".to_string(), "b".to_string(), "c".to_string()];
    let mut r = v.iter()
        .rev()
        .fold(String::new(), |r, c| r + c.as_str() + ".");
    r.pop();
    println!("{}", r);
}

The addition operation on String takes its left operand by value and pushes the second operand in-place, which is very nice - it does not cause any reallocations. You don't even need to clone() the contained strings.

I think, however, that the lack of concat()/connect() methods on iterators is a serious drawback. It bit me a lot too.

like image 122
Vladimir Matveev Avatar answered Oct 20 '22 20:10

Vladimir Matveev


I don't know if they've heard our Stack Overflow prayers or what, but the itertools crate happens to have just the method you need - join.

With it, your example might be laid out as follows:

use itertools::Itertools;
let v = ["a", "b", "c"];
let connected = v.iter().rev().join(".");
like image 34
ArtemGr Avatar answered Oct 20 '22 20:10

ArtemGr