如何打印 Vec?
Posted
技术标签:
【中文标题】如何打印 Vec?【英文标题】:How to print a Vec? 【发布时间】:2015-07-30 22:53:51 【问题描述】:我尝试了以下代码:
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>
实现了这个特性吗?
【问题讨论】:
【参考方案1】:let v2 = vec![1; 10];
println!(":?", v2);
用于字符串和其他可以直接显示给用户的值。没有一种方法可以向用户显示矢量。
:?
格式化程序可以用来调试它,它看起来像:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Display
是提供 背后方法的特征,
Debug
是为:?
提供的方法
【讨论】:
这是问题标题的正确答案。也适用于数组,不仅是vec!
有没有办法把矢量格式化得更漂亮,不只是单行打印?
@Anatoly 您可以使用替代说明符:#?
使输出分布多行【参考方案2】:
有人为
Vec<T>
实现这个特性吗?
没有。
令人惊讶的是,这是一个明显正确的答案;这很少见,因为证明事物不存在通常很难或不可能。那我们怎么能这么确定呢?
Rust 有非常严格的一致性规则,impl Trait for Struct
只能做到:
Trait
在同一个箱子里
或与Struct
在同一个板条箱中
别无他处;让我们try it:
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
此外,要使用 trait,它需要在范围内(因此,您需要链接到它的 crate),这意味着:
您已与Display
的板条箱和Vec
的板条箱链接
既不为Vec
实现Display
因此我们得出结论,没有人为Vec
实现Display
。
作为一种变通方法,如 Manishearth 所述,您可以使用 Debug
特征,该特征可通过 ":?"
作为格式说明符调用。
【讨论】:
报错E0210是否意味着只允许在文件collections/vec.rs中实现trait Display? @highfly22:我的理解是它应该在同一个箱子里,不一定是同一个文件。 什么?所以我不能在模块中临时添加一个 Display trait impl,我需要它作为另一个 crate 中的类型? @BitTickler:不。解决方案是声明一个新类型:struct Mine(That3rdPartyType);
,然后是impl Display for Mine
。
这里是一个“新类型”的例子:play.rust-lang.org/…【参考方案3】:
如果您知道向量包含的元素的类型,您可以创建一个以向量为参数的结构,并为该结构实现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);
【讨论】:
不要求你必须知道元素的确切类型;你可以use a generic and allow any type that implementsDisplay
。
不幸的是 shepmasters gist 不再起作用了。我已经从这里的示例中重建了一个:play.rust-lang.org/…【参考方案4】:
这是一个也适合你的单行:
println!("[]", v2.iter().fold(String::new(), |acc, &num| acc + &num.to_string() + ", "));
Here 是 一个可运行的例子。
在我自己的情况下,我从函数调用中收到了Vec<&str>
。我不想将函数签名更改为自定义类型(我可以为此实现 Display
特征)。
对于我的一个案例,我能够将我的 Vec
的显示转换为我直接与 println!()
一起使用的单行,如下所示:
println!("", myStrVec.iter().fold(String::new(), |acc, &arg| acc + arg));
(lambda 可以适应不同的数据类型,或者更简洁的Display
trait 实现。)
【讨论】:
【参考方案5】:是否有任何理由不逐项编写向量的内容而无需以前的收集? *)
use std::fmt::Display, Formatter, Error;
struct NumVec(Vec<u32>);
impl Display for NumVec
fn fmt(&self, f: &mut Formatter) -> Result<(), Error>
let v = &self.0;
if v.len() == 0
return Ok(());
for num in &v[0..v.len() - 1]
if let Err(e) = write!(f, ", ", &num.to_string())
return Err(e);
write!(f, "", &v[v.len() - 1])
fn main()
let numbers = NumVec(vec![1; 10]);
println!("", numbers);
*) 不,没有。
因为我们想要显示一些东西,所以Display
trait 是肯定实现的。所以这是正确的Rust,因为:文档说ToString trait:
“对于任何实现了Display
trait 的类型,这个特征都会自动实现。因此,ToString
不应该直接实现:Display
应该被实现,你会得到ToString
实现免费。”
特别是在空间有限的微控制器上,我肯定会采用这种解决方案并立即编写。
【讨论】:
以上是关于如何打印 Vec?的主要内容,如果未能解决你的问题,请参考以下文章