🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

2回答

2346閲覧

enumをキーとしたハッシュマップを作成したい

asobinin

総合スコア69

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2021/03/03 10:16

編集2021/03/03 12:14

enumの値を無視して型だけで判別するハッシュマップを作成したいのですが、構造体でラッピングしても値まで完全一致でなければヒットしてくれません。どのようにすればこれが実現できますか。

Rust

1use std::collections::HashMap; 2 3#[derive(Debug, Hash, Eq, PartialEq)] 4enum Animal { 5 Dog, 6 Cat(i32), 7 Bird { 8 name: String, 9 age: i32, 10 }, 11} 12 13fn main() { 14 // やりたいこと 15 let foo: HashMap<Animal, i32> = vec![ 16 (Animal::Dog, 3), (Animal::Cat, 2), (Animal::Bird, 1)] 17 .into_iter().collect(); 18 let bar = Animal::Cat(10); 19 assert_eq!(2, foo[&bar]) 20}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

HashMapはキーに完全に一致したものを取り出すためのデータ構造ですので、ご質問のような部分一致したものを取り出すようなことはできません。また、Animal型についても、コードの「やりたいこと」にあるようなフィールド値を省略してCatのようなバリアントだけの値を作ることもできません。

たとえば、以下のように、フィールドを持たないenumと、フィールドを持つenumの両方を定義するのはどうでしょうか?

rust

1use std::collections::HashMap; 2 3/// 動物の種類(バリアントだけでフィールドを持たない) 4#[derive(Debug, Hash, Eq, PartialEq)] 5enum AnimalKind { 6 Dog, 7 Cat, 8 Bird, 9} 10 11/// 動物(いくつかのバリアントはフィールドを持つ) 12#[derive(Debug, Eq, PartialEq)] 13enum Animal { 14 Dog, 15 Cat(i32), 16 Bird { name: String, age: i32 }, 17} 18 19fn main() { 20 let foo: HashMap<AnimalKind, (Animal, i32)> = vec![ 21 (AnimalKind::Dog, (Animal::Dog, 3)), 22 (AnimalKind::Cat, (Animal::Cat(10), 2)), 23 (AnimalKind::Bird, 24 (Animal::Bird {name: "Tweety".to_string(), age: 3}, 1), 25 ), 26 ] 27 .into_iter() 28 .collect(); 29 let bar = AnimalKind::Cat; 30 assert_eq!(foo[&bar], (Animal::Cat(10), 2)); 31}

投稿2021/03/03 10:58

tatsuya6502

総合スコア2046

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

キーをすべてAnimalの値から取るのであればstd::mem::discriminantが使えると思います。

他の手段としてはenum AnimalKind { Dog, Cat, Bird }Animal::kind: fn(&self) -> AnimalKindを作るという方法でしょうか。AnimalKindについてはenum-mapというクレートを使えば扱いやすくなり、パフォーマンスも向上するかと思います。(直接Animalには使えないので注意)

diff

1-use std::collections::HashMap; 2+use std::{ 3+ collections::HashMap, 4+ mem::{self, Discriminant}, 5+}; 6 7 #[derive(Debug, Hash, Eq, PartialEq)] 8 enum Animal { 9 Dog, 10 Cat(i32), 11 Bird { name: String, age: i32 }, 12 } 13 14 fn main() { 15 // やりたいこと 16- let foo: HashMap<Animal, i32> = vec![(Animal::Dog, 3), (Animal::Cat, 2), (Animal::Bird, 1)] 17- .into_iter() 18- .collect(); 19+ let foo: HashMap<Discriminant<Animal>, i32> = vec![ 20+ (mem::discriminant(&Animal::Dog), 3), 21+ (mem::discriminant(&Animal::Cat(0)), 2), 22+ ( 23+ mem::discriminant(&Animal::Bird { 24+ name: "".to_owned(), 25+ age: 0, 26+ }), 27+ 1, 28+ ), 29+ ] 30+ .into_iter() 31+ .collect(); 32 let bar = Animal::Cat(10); 33- assert_eq!(2, foo[&bar]) 34+ assert_eq!(2, foo[&mem::discriminant(&bar)]) 35 }

投稿2021/03/03 10:49

qryxip

総合スコア86

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

asobinin

2021/03/03 12:06

私の求めていたものがstd::memの中にあったのですね・・・ 盲点でした
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問