verilog書く人

自称ASIC設計者です。どなたかkaggle一緒に出ましょう。

Rustでdefaultdict

RustでPythonのDefaultDictのようにデフォルト値を持ったハッシュマップを使いたい場合、 entry APIを使って、以下のようにすればよい。

    let mut normal_map = std::collections::HashMap::<i32, i32>::new();

    // normal_map[3]を呼ぶ。ただし、存在しなければmap[3] = 5とする。
    // println!("{:?}", normal_map[3]); はできないことに注意する。
    println!("{:?}", *normal_map.entry(3).or_insert(5));  // 5

    // normal_map[4]に1を足す。ただし、存在しなければmap[4] = 5としてから1を足す。
    (*normal_map.entry(4).or_insert(5)) += 1;
    println!("{:?}", *normal_map.entry(4).or_insert(5));  // 6

    // normal_map[5]を6とする。ただし、存在しなければmap[5] = 5としてから6を代入する。
    (*normal_map.entry(5).or_insert(5)) = 6;
    println!("{:?}", *normal_map.entry(5).or_insert(5));  // 6

ここで、HashMapに格納される値の型は基本型でなくてもよい。 例えば、Vecのようなコンテナでもかまわない。

    let mut normal_map = std::collections::HashMap::<i32, Vec<i32>>::new();

    // normal_map[3]を呼ぶ。ただし、存在しなければmap[3] = vec![]とする。
    println!("{:?}", *normal_map.entry(3).or_insert(vec![]));  // []

    // normal_map[4]に2をpushする。ただし、存在しなければmap[4] = vec![]としてからpushする。
    (*normal_map.entry(4).or_insert(vec![])).push(2);  // [1]
    println!("{:?}", normal_map[&4]);

しかし、entry APIを使ったアクセスは書き込みだけでなく、値が格納されているかわからない場合には、読み込みの度にもmap.entry(3).or_insert(5)してdereferenceしなければならない。

でなければ値が格納されていない要素にアクセスされた場合、panicが発生する。

少々めんどくさい。

そういう時は、

GitHub - JelteF/defaultmap: A defaultmap for rust

を使う。これはデフォルト値をDefaultHashMap::new()で指定できるHashMapである。 defaultmapを使って、上記の例を書き直すと以下のようになる。

    let mut normal_map = DefaultHashMap::<i32, i32>::new(5);
    println!("{}", normal_map[3]);
    normal_map[4] += 1;
    println!("{}", normal_map[4]);
    normal_map[5] = 6;
    println!("{}", normal_map[4]);

初期値は当然、コンテナ型でもよい。

    let mut normal_map = DefaultHashMap::<i32, Vec<i32>>::new(vec![]);
    println!("{:?}", normal_map[3]);
    normal_map[4].push(2);
    println!("{:?}", normal_map[4]);

ほぼPythonのDefaultDictのように使えるのでかなり便利である。

stdに入っていてほしいレベル。

ここで、[]演算子を使ってアクセスする際にキーは参照ではないことに注意されたい。

normal_map[4]のように値を使う。(HashMapは[&4])

プログラミングRust

プログラミングRust