web-dev-qa-db-ja.com

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>にこの特性を実装している人はいますか?

46
highfly22

誰でもこの特性を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が示すように、Debugトレイトを使用できます。これは、"{:?}"を介してフォーマット指定子として呼び出すことができます。

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

{}は、ユーザーに直接表示できる文字列およびその他の値用です。ユーザーにベクターを表示する唯一の方法はありません。

{:?}フォーマッタを使用してデバッグでき、次のようになります。

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

Display{}の背後にあるメソッドを提供する特性であり、Debug{:?}用です

58
Manishearth

ベクトルに含まれる要素の型がわかっている場合は、引数としてベクトルを取る構造体を作成し、その構造体に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);
}
18
evilone

これもあなたのために働くはずのワンライナーです:

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

ここ は実行可能な例です。


私の場合、関数呼び出しから_Vec<&str>_を受け取っていました。関数のシグネチャをカスタムタイプ(Display特性を実装できるもの)に変更したくありませんでした。

私の1つ目のケースでは、次のようにVecの表示をprintln!()で直接使用するワンライナーに変えることができました。

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

(ラムダは、さまざまなデータ型で使用するために、またはより簡潔なDisplay trait実装に適合させることができます。)

6
U007D