web-dev-qa-db-fra.com

Comment imprimer un Vec?

J'ai essayé le code suivant:

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

Mais le compilateur se plaint:

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`

Est-ce que quelqu'un implémente ce trait pour Vec<T>?

46
highfly22

Est-ce que quelqu'un implémente ce trait pour Vec<T>?

Non.

Et étonnamment, c'est une réponse manifestement correcte; ce qui est rare car prouver l'absence de choses est généralement difficile voire impossible. Alors, comment pouvons-nous être si certains?

La rouille a des règles de cohérence très strictes, le impl Trait for Struct ne peut être fait que:

  • soit dans la même caisse que Trait
  • ou dans la même caisse que Struct

et nulle part ailleurs; nous allons essayez-le :

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

rendements:

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

De plus, pour utiliser un trait, il doit être dans la portée (et donc, vous devez être lié à sa caisse), ce qui signifie que:

  • vous êtes lié à la fois à la caisse de Display et à la caisse de Vec
  • ni implémenter Display pour Vec

et nous amène donc à conclure que personne n'implémente Display pour Vec.


Comme solution de contournement, comme indiqué par Manishearth, vous pouvez utiliser le trait Debug, qui est invocable via "{:?}" comme spécificateur de format.

39
Matthieu M.
let v2 = vec![1; 10];
println!("{:?}", v2);

{} est pour les chaînes et autres valeurs qui peuvent être affichées directement pour l'utilisateur. Il n'y a pas de moyen unique de montrer un vecteur à un utilisateur.

Le {:?} le formateur peut être utilisé pour le déboguer, et il ressemblera à:

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

Display est le trait qui fournit la méthode derrière {} et Debug est pour {:?}

58
Manishearth

Si vous connaissez le type des éléments que contient le vecteur, vous pouvez créer une structure qui prend le vecteur comme argument et implémenter Display pour cette structure.

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);
}
18
evilone

Voici un one-liner qui devrait également fonctionner pour vous:

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

Ici est un exemple exécutable.


Dans mon propre cas, je recevais un Vec<&str> D'un appel de fonction. Je ne voulais pas changer la signature de la fonction en un type personnalisé (pour lequel je pouvais implémenter le trait Display).

Pour mon cas unique, j'ai pu transformer l'affichage de mon Vec en un seul revêtement que j'ai utilisé avec println!() directement comme suit:

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

(Le lambda peut être adapté pour être utilisé avec différents types de données ou pour des implémentations de traits Display plus concises.)

6
U007D