什么是打印在Rust中用空格分隔的迭代器的惯用方法?

时间:2016-04-29 15:09:48

标签: rust

我只想要一个空格分隔Stringstd::env::args()获得的参数变量,我使用fold函数创建了这样的参数:

std::env::args()
    .fold("".to_string(), |accum, s| accum + &s + " ")

然而,这会在最后产生额外的空间,这是不需要的。我尝试使用truncate函数,但truncate没有返回String,只修改现有的String,这也需要创建一个中间版绑定以便使用String的{​​{1}}调用来定义截断的len()应该有多长(由于Rust&s,它本身需要中间绑定我相信当前的词汇借用规则!)

4 个答案:

答案 0 :(得分:6)

  

在Rust中打印所有命令行参数的惯用方法是什么?

fn main() {
    let mut args = std::env::args();

    if let Some(arg) = args.next() {
        print!("{}", arg);

        for arg in args {
            print!(" {}", arg);
        }
    }
}

或者更好地使用Itertools'format

use itertools::Itertools; // 0.8.0

fn main() {
    println!("{}", std::env::args().format(" "));
}
  

我只想要一个空格分隔String

fn args() -> String {
    let mut result = String::new();
    let mut args = std::env::args();

    if let Some(arg) = args.next() {
        result.push_str(&arg);

        for arg in args {
            result.push(' ');
            result.push_str(&arg);
        }
    }

    result
}

fn main() {
    println!("{}", args());
}

或者

fn args() -> String {
    let mut result = std::env::args().fold(String::new(), |s, arg| s + &arg + " ");
    result.pop();
    result
}

fn main() {
    println!("{}", args());
}

如果您使用Itertools,join很有用:

use itertools::Itertools; // 0.8.0

fn args() -> String {
    std::env::args().join(" ")
}

fn main() {
    println!("{}", args());
}

在其他情况下,您可能希望使用intersperse

use itertools::Itertools; // 0.8.0

fn args() -> String {
    std::env::args().intersperse(" ".to_string()).collect()
}

fn main() {
    println!("{}", args());
}

请注意,这不如其他选项有效,因为每次迭代都会克隆String

答案 1 :(得分:1)

这是一个带有迭代器和零非标准库依赖项的解决方案

(性能方面,这在发布模式下大放异彩,优化已开启 [playground])

use std::iter::once;

fn join_iter<T>(
    mut iter: impl Iterator<Item = T>,
    sep: impl Fn(&T) -> T,
) -> impl Iterator<Item = T> {
    iter.next()
        .into_iter()
        .chain(iter.flat_map(move |s| once(sep(&s)).chain(once(s))))
}

fn examples() {
    let iter = [1, 3, 5, 7, 9].iter().cloned();
    println!("{:?}", join_iter(iter, |v| v - 1).collect::<Vec<_>>());
    // [1, 2, 3, 4, 5, 6, 7, 8, 9]

    let iter = ["Hello", "World"].iter().cloned();
    let sep = ", ";
    println!("{:?}", join_iter(iter, |_| sep).collect::<String>());
    // "Hello, World"
}

fn args() -> String {
    join_iter(std::env::args(), |_| " ".to_string()).collect()
}

fn main() {
    examples();

    println!("{}", args());
}

答案 2 :(得分:0)

这是

的替代方案
  

我只想要从String

获取的参数变量的空格分隔std::env::args()
fn args_string() -> String {
    let mut out = String::new();
    let mut sep = "";
    for arg in std::env::args() {
        out.push_str(sep);
        out.push_str(&*arg);
        sep = " ";
    }
    out
}

pub fn main() {
    println!("{}", args_string());
}

答案 3 :(得分:0)

这是一个使用 fold

的版本
fn join<I, T, D>(iter: I, separator: D) -> String
where
    T: Display,
    D: Display,
    I: Iterator<Item = T>,
{
    match iter.fold(None, |a:Option<String>, b| {
        Some(match a {
            None => format!("{}", &b),
            Some(mut a) => {
                write!(a, "{}{}", separator, b).unwrap();
                a
            }
        })
    }) {
        None => String::new(),
        Some(rval) => rval,
    }
}