LINUX.ORG.RU

краткий и эффективный &str join

 ,


0

5

нагуглил только такое:

fn reverse_words(s: &str) -> String {
  s.split_whitespace().rev().collect::<Vec<&str>>().join(" ")
}

но тут лишний вектор создается в куче. мой вариант, без лишней аллокации:

fn reverse_words(str: &str) -> String {
    let mut iter = str.split_whitespace().rev();
    if let Some(x) = iter.next() {
        let mut result = String::with_capacity(str.len());
        result += x;
        for x in iter {
            result += " ";
            result += x;
        }
        result
    } else {
        String::new()
    }
}

как сделать кратко и эффективно? заодно если расскажете, как можно сократить лапшу if let с итератором, будет вообще прекрасно

Ответ на: комментарий от Deleted

fold-у нужно передать init-аргумент; все равно такая же лапша будет, только со split_first

покажи свой вариант; желательно^Wсамо собой, чтобы строчки соединялись в одном буфере

MyTrooName ★★★★★ ()
Последнее исправление: MyTrooName (всего исправлений: 1)

Если нужен произвольный сепаратор, то делаем так как в реализации join, используем флаг.

fn reverse_words(src: &str, sep: &str) -> String {
    let mut res = String::with_capacity(src.len());
    let mut first = true;
    for it in src.split_whitespace().rev() {
        if first {
            first = false;
        } else {
            res.push_str(sep);
        }
        res.push_str(it);
    }
    res
}

https://is.gd/oV7X8d

pftBest ★★★★ ()
Ответ на: комментарий от dzidzitop

split_whitespace() возвращает DoubleEndedIterator, это такой итератор у которого кроме функции next() которая идет вперед по строке, есть еще функция next_back() которая идет от конца строки к началу.

А rev() просто меняет местами функции next() и next_back().

pftBest ★★★★ ()