如何打印Vec?


75

我尝试了以下代码:

fn main() {
    let v2 = vec![1; 10];
    println!("{}", v2);
}

但是编译器抱怨:

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`

有没有人实现此特征Vec<T>

Answers:


59

有没有人实现此特征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(())
    }
}

产量:

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

此外,要使用特征,它必须在范围内(因此,您需要链接到其板条箱),这意味着:

  • 您与的板条箱Display和的板条箱都链接了Vec
  • 既实现DisplayVec

因此使我们得出结论,没有一个工具DisplayVec


作为解决方法,如Manishearth所指出的,您可以使用Debugtrait,可以将其"{:?}"作为格式说明符调用。


错误E0210是否仅允许在文件collections / vec.rs中实现特征显示?
highfly22

1
@ highfly22:我的理解是,它应该位于同一包装箱中,而不一定是同一文件。
Matthieu M.

1
什么?因此,我无法在模块中的其他包装箱中临时添加Display trait impl吗?
BitTickler '16

3
@BitTickler:否。解决方案是声明一个新类型:struct Mine(That3rdPartyType);然后声明impl Display for Mine
Matthieu M.

4
这里是一个“NEWTYPE”的例子:play.rust-lang.org/...
zzeroo

97
let v2 = vec![1; 10];
println!("{:?}", v2);

{}用于字符串和其他可以直接显示给用户的值。没有向用户显示矢量的单一方法。

{:?}格式可以用来调试它,它看起来像:

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Display是提供方法背后的性状{},并且Debug是用于{:?}


23

如果知道向量包含的元素的类型,则可以制作一个将向量作为参数的结构,并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);
}

2
不需要您必须知道元素的确切类型;您可以使用泛型并允许实现的任何类型Display
Shepmaster '16

1
不幸的是,shepmasters gist不再起作用。我有一个重建从这里的例子:play.rust-lang.org/...
zzeroo

8

这是一种单线也应为您工作:

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));

(lambda可以适合与不同的数据类型一起使用,或用于更简洁的Display特征实现。)


-1
Does anyone implement this trait for Vec<T>?

是的,这是我的做法

fn main() {
    let a = vec![10,12,13];
    println!("{:?}",display(a));
}


use std::fmt::Debug;
fn display<T: Debug>(a: Vec<T>) -> Vec<T> {
    let mut new_vec : Vec<T> = Vec::new();
    
    for i in a {
        new_vec.push(i);
    }
    return new_vec
} 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.