如何打印Vec?

hig*_*y22 50 println rust

我尝试了以下代码:

fn main() {
    let v2 = vec![1; 10];
    println!("{}", v2);
}
Run Code Online (Sandbox Code Playgroud)

但编译器抱怨说:

error[E0277]: `std::vec::Vec<{integer}>` doesn't implement `std::fmt::Display`
 --> src/main.rs:3:20
  |
3 |     println!("{}", v2);
  |                    ^^ `std::vec::Vec<{integer}>` cannot be formatted with the default formatter
  |
  = help: the trait `std::fmt::Display` is not implemented for `std::vec::Vec<{integer}>`
  = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
  = note: required by `std::fmt::Display::fmt`
Run Code Online (Sandbox Code Playgroud)

有没有人实现这个特性Vec<T>

Man*_*rth 60

let v2 = vec![1; 10];
println!("{:?}", v2);
Run Code Online (Sandbox Code Playgroud)

{}用于字符串和其他值,可以直接显示给用户.没有单一的方法向用户显示矢量,但{:?}可以用来调试它,它看起来像:

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Run Code Online (Sandbox Code Playgroud)

Display是提供后面的方法中的特征{},并且Debug是用于{:?}

  • @Anatoly,您可以使用替代说明符 `{:#?}` 使输出分布多行 (8认同)

Mat*_* M. 42

有没有人实现这个特性Vec<T>

没有.

令人惊讶的是,这是一个明确正确的答案; 这是罕见的,因为证明没有东西通常很难或不可能.那么我们怎么能这么肯定呢?

Rust有一个非常严格的一致性规则,impl Trait for Struct只能这样做:

  • 或者在同一箱子里 Trait
  • 或者在同一箱子里 Struct

而在其他地方; 让我们试一试:

impl<T> std::fmt::Display for Vec<T> {
    fn fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        Ok(())
    }
}
Run Code Online (Sandbox Code Playgroud)

收益率:

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
 --> src/main.rs:1:1
  |
1 | impl<T> std::fmt::Display for Vec<T> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
  |
  = note: only traits defined in the current crate can be implemented for a type parameter
Run Code Online (Sandbox Code Playgroud)

此外,要使用a Display,它需要在范围内(因此,您需要链接到其包),这意味着:

  • 你把它与箱子Vec和板条箱都联系在一起Display
  • 既实现VecDisplay

因此使我们得出结论,没有一个实现VecDebug.


作为一种解决方法,如Manishearth所示,您可以使用"{:?}"特征,该特征可Vec<T>作为格式说明符调用.

  • 这是一个"newtype"示例:https://play.rust-lang.org/?gist = b28b96a28d081601e2e09b1fc26f8ade&version=stable&mode=debug&edition=2015 (3认同)
  • @BitTickler:不.解决方案是声明一个新类型:`struct Mine(That3rdPartyType);`然后`impl Display for Mine`. (2认同)

evi*_*one 20

如果你知道向量包含的元素的类型,你可以创建一个结构,它将vector作为参数并Display为该结构实现.

use std::fmt::{Display, Formatter, Error};

struct NumVec(Vec<u32>);

impl Display for NumVec {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let mut comma_separated = String::new();

        for num in &self.0[0..self.0.len() - 1] {
            comma_separated.push_str(&num.to_string());
            comma_separated.push_str(", ");
        }

        comma_separated.push_str(&self.0[self.0.len() - 1].to_string());
        write!(f, "{}", comma_separated)
    }
}

fn main() {
    let numbers = NumVec(vec![1; 10]);
    println!("{}", numbers);
}
Run Code Online (Sandbox Code Playgroud)

  • 没有要求您必须知道元素的 * 确切 * 类型;你可以[使用泛型并允许实现`Display`的任何类型](http://play.integer32.com/?gist=38a0d87690419c4c1e7280c95e155d0b&amp;version=stable)。 (2认同)
  • 不幸的是,shepmasters gist 不再起作用了。我从这里的示例中重建了一个:https://play.rust-lang.org/?gist=b28b96a28d081601e2e09b1fc26f8ade&amp;version=stable&amp;mode=debug&amp;edition=2015 (2认同)

Dan*_*ger 8

从 Rust 1.58 开始,有一种稍微更简洁的方法来打印向量(或任何其他变量)。这使您可以将要打印的变量放在花括号内,而不需要将其放在末尾。对于打印向量所需的调试格式,您可以添加:?大括号,如下所示:

fn main() {
    let v2 = vec![1; 10];
    println!("{v2:?}");
}
Run Code Online (Sandbox Code Playgroud)


opt*_*evo 7

有时您不想使用类似已接受答案的内容

let v2 = vec![1; 10];
println!("{:?}", v2);
Run Code Online (Sandbox Code Playgroud)

因为您希望每个元素使用其Display特征而不是其Debug特征来显示;然而,如前所述,由于 Rust 的一致性规则,您无法实现Displayon 。Vec您可以使用如下函数实现Display更通用的解决方案,而不是使用该特征实现包装器结构:

use std::fmt;

pub fn iterable_to_str<I, D>(iterable: I) -> String
where
    I: IntoIterator<Item = D>,
    D: fmt::Display,
{
    let mut iterator = iterable.into_iter();

    let head = match iterator.next() {
        None => return String::from("[]"),
        Some(x) => format!("[{}", x),
    };
    let body = iterator.fold(head, |a, v| format!("{}, {}", a, v));
    format!("{}]", body)
}
Run Code Online (Sandbox Code Playgroud)

这不需要将向量包装在结构中。只要it实现IntoIterator并且元素类型实现Display,您就可以调用:

println!("{}", iterable_to_str(it));
Run Code Online (Sandbox Code Playgroud)


U00*_*07D 6

这里是一个班轮这也应该为你工作:

println!("[{}]", v2.iter().fold(String::new(), |acc, &num| acc + &num.to_string() + ", "));

是一个可运行的示例。


就我自己来说,我是接受Vec<&str>从一个函数调用。我不想函数签名更改为自定义的类型(这我可以实现的Display特性)。

对于我的之一的情况下,我能够把我的显示Vec进我与使用一衬垫println!()直接如下:

println!("{}", myStrVec.iter().fold(String::new(), |acc, &arg| acc + arg));
Run Code Online (Sandbox Code Playgroud)

(拉姆达可适于具有不同数据类型的使用,或者用于更简洁Display性状实现。)