Подтвердить что ты не робот

Как распечатать 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>?

4b9b3361

Ответ 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.)