Как распечатать Vec?
Я попробовал следующий код:
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
Кто-нибудь реализует эту черту для 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
- ни внедрить
Display
для Vec
и поэтому приводит нас к выводу, что никто не реализует Display
для Vec
.
В качестве обходного пути, как указывает Manishearth, вы можете использовать черту Debug
, которая вызывается через "{:?}"
качестве спецификатора формата.
Ответ 2
let v2 = vec![1; 10];
println!("{:?}", v2);
{}
для строк и других значений, которые могут быть отображены непосредственно пользователю. Там нет единого способа показать вектор пользователю.
Формататор {:?}
Можно использовать для его отладки, и он будет выглядеть так:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Display
- это черта, которая обеспечивает метод {}
, а Debug
для {:?}
Ответ 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);
}
Ответ 4
Вот один лайнер, который также должен работать для вас:
println!("[{}]", v2.iter().fold(String::new(), |acc, &num| acc + &num.to_string() + ", "));
Здесь
runnable example.
В моем случае я получал Vec<&str>
от вызова функции. Я не хотел менять подпись функции на пользовательский тип (для которого я мог реализовать признак Display
).
В моем случае я смог превратить отображение моего Vec
в однострочный, который я использовал с println!()
, следующим образом:
println!("{}", myStrVec.iter().fold(String::new(), |acc, &arg| acc + arg));
(Лямбда может быть адаптирована для использования с разными типами данных или для более сжатых реализаций реализации Display
.)