やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

RustのコレクションHashMap型

 使い方がややこしい。C#のほうが直感的。

成果物

参考

コード

use

use std::collections::HashMap;

 最初に必要。

生成

let mut map = HashMap::new();

 空のハッシュマップを生成する。mutにしないとinsertなどができず使い物にならない。

挿入

let mut map = HashMap::new();
map.insert("A".to_string(), 100);
map.insert("B".to_string(), 100);

 insert(キー, 値)とする。

 ドキュメントではString型だが、str型でもできた。

 なお、同一キーにおける2回目以降のinsertは、値を更新することになる。

所有権

 所有権はムーブする。

let key = "key1".to_string();
let value = 100;
let mut map = HashMap::new();
map.insert(key, value); // 所有権がムーブされる(key,value)    error[E0382]: use of moved value: `key`
println!("{:?}", map);
println!("{} {}", key, value); // key, valueの所有権を失っているのでエラー

取得

let mut map = HashMap::new();
map.insert("A".to_string(), 100);
println!("{:?}", scores.get(&"A".to_string())); // Some(1)
  • get()Option<&V>を返す

 なんか複雑。以下のせい。

  • &
  • to_string()がウザい
  • {:?}

 型やそれにより生じる違いによってコードを書かねばならない苦痛。scores.get("A"); // 1みたいに使いたいのだが……。

 もう少し簡略化したのが以下。

let mut map = HashMap::new();
map.insert("A".to_string(), 100);
println!("{:?}", scores.get("A")); // Some(1)

 文字列リテラルならgetの引数に&が不要。

  1. なぜget&が必要か?
    • 引数の所有権が呼出元からget関数へムーブしないように、そう設計したと思われる
  2. なぜ文字列リテラルなら&が不要か?
  3. なぜString型でinsertしたのにstr型でgetできるのか?
    • わからん

走査

let mut map = HashMap::new();
map.insert("A".to_string(), 1);
map.insert("B".to_string(), 2);
for (key, value) in &scores {
    println!("{}: {}", key, value);
}

カウント

let text = "A B A C";
let mut words_count = HashMap::new();
for word in text.split_whitespace() {
    let count = words_count.entry(word).or_insert(0);
    *count += 1;
}
println!("{:?}", words_count);
{"C": 1, "A": 2, "B": 1}
  • struct HashMap
    • entry(): Entryを取得する
  • enum HashMap::Entry: キーと値の型
    • or_insert(): 値の可変参照を返す。ただし値が空のときは引数値を設定する

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで