配列
固定長のコレクションです。
// 配列の宣言
let numbers: [i32; 5] = [1, 2, 3, 4, 5];
let zeros = [0; 5]; // [0, 0, 0, 0, 0]
// 要素へのアクセス
println!("{}", numbers[0]); // 1
println!("{}", numbers.len()); // 5
// スライス
let slice = &numbers[1..3]; // [2, 3]
// イテレート
for num in &numbers {
println!("{}", num);
}
Vec(ベクタ)
可変長のコレクションです。
// 作成
let mut vec: Vec<i32> = Vec::new();
let vec2 = vec![1, 2, 3]; // マクロで作成
// 追加
vec.push(1);
vec.push(2);
vec.push(3);
// 取得
println!("{}", vec[0]); // 1
println!("{:?}", vec.get(10)); // None(安全なアクセス)
// 更新
vec[0] = 10;
// 削除
vec.pop(); // 末尾を削除
vec.remove(0); // インデックスで削除
// 長さと容量
println!("長さ: {}", vec.len());
println!("容量: {}", vec.capacity());
// イテレート
for num in &vec {
println!("{}", num);
}
// 変更しながらイテレート
for num in &mut vec {
*num *= 2;
}
Vec の操作
let mut numbers = vec![3, 1, 4, 1, 5, 9, 2, 6];
// ソート
numbers.sort();
println!("{:?}", numbers); // [1, 1, 2, 3, 4, 5, 6, 9]
// 逆順
numbers.reverse();
// 検索
let found = numbers.contains(&5);
let position = numbers.iter().position(|&x| x == 5);
// スライス
let slice = &numbers[0..3];
// 結合
let mut a = vec![1, 2];
let mut b = vec![3, 4];
a.append(&mut b);
// フィルタリング
let evens: Vec<i32> = numbers.into_iter().filter(|x| x % 2 == 0).collect();
String
UTF-8エンコードされた文字列です。
// 作成
let mut s = String::new();
let s2 = String::from("Hello");
let s3 = "World".to_string();
// 追加
s.push_str("Hello");
s.push(' ');
s.push_str("World");
// 連結
let hello = String::from("Hello");
let world = String::from("World");
let hello_world = hello + " " + &world; // helloは移動
// format!マクロ
let s = format!("{} {}", "Hello", "World");
// スライス
let hello = &s[0..5];
// 長さ
println!("バイト数: {}", s.len());
println!("文字数: {}", s.chars().count());
// イテレート
for c in s.chars() {
println!("{}", c);
}
文字列操作
let text = " Hello, World! ";
// トリム
let trimmed = text.trim();
// 分割
let words: Vec<&str> = text.split(',').collect();
// 検索
let contains = text.contains("World");
let starts = text.starts_with(" H");
let ends = text.ends_with("! ");
// 置換
let replaced = text.replace("World", "Rust");
// 大文字・小文字
let upper = text.to_uppercase();
let lower = text.to_lowercase();
HashMap
キーと値のペアを格納します。
use std::collections::HashMap;
// 作成
let mut scores: HashMap<String, i32> = HashMap::new();
// 追加
scores.insert(String::from("太郎"), 85);
scores.insert(String::from("花子"), 92);
// 取得
let score = scores.get("太郎");
match score {
Some(s) => println!("太郎: {}", s),
None => println!("見つかりません"),
}
// 存在しない場合のみ挿入
scores.entry(String::from("次郎")).or_insert(78);
// 更新
scores.insert(String::from("太郎"), 90);
// 削除
scores.remove("花子");
// イテレート
for (key, value) in &scores {
println!("{}: {}", key, value);
}
HashMap の応用
use std::collections::HashMap;
// 単語カウント
fn word_count(text: &str) -> HashMap<String, i32> {
let mut counts = HashMap::new();
for word in text.split_whitespace() {
let count = counts.entry(word.to_lowercase()).or_insert(0);
*count += 1;
}
counts
}
let text = "hello world hello rust hello";
let counts = word_count(text);
for (word, count) in &counts {
println!("{}: {}", word, count);
}
HashSet
重複のない値の集合です。
use std::collections::HashSet;
let mut set: HashSet<i32> = HashSet::new();
// 追加
set.insert(1);
set.insert(2);
set.insert(2); // 重複は無視
println!("{}", set.len()); // 2
// 存在確認
println!("{}", set.contains(&1)); // true
// 削除
set.remove(&1);
// 集合演算
let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
let b: HashSet<_> = [3, 4, 5].iter().cloned().collect();
// 和集合
let union: HashSet<_> = a.union(&b).cloned().collect();
// 積集合
let intersection: HashSet<_> = a.intersection(&b).cloned().collect();
// 差集合
let difference: HashSet<_> = a.difference(&b).cloned().collect();
イテレータ
let numbers = vec![1, 2, 3, 4, 5];
// iter() - 不変参照
for n in numbers.iter() {
println!("{}", n);
}
// iter_mut() - 可変参照
let mut numbers = vec![1, 2, 3];
for n in numbers.iter_mut() {
*n *= 2;
}
// into_iter() - 所有権を取得
let numbers = vec![1, 2, 3];
for n in numbers.into_iter() {
println!("{}", n);
}
// numbers はここでは使えない
// イテレータアダプタ
let sum: i32 = (1..=100)
.filter(|n| n % 2 == 0) // 偶数のみ
.map(|n| n * n) // 二乗
.take(10) // 最初の10個
.sum(); // 合計
実践例:学生成績管理
use std::collections::HashMap;
#[derive(Debug)]
struct Student {
name: String,
scores: Vec<i32>,
}
impl Student {
fn new(name: &str) -> Self {
Student {
name: name.to_string(),
scores: Vec::new(),
}
}
fn add_score(&mut self, score: i32) {
self.scores.push(score);
}
fn average(&self) -> f64 {
if self.scores.is_empty() {
return 0.0;
}
self.scores.iter().sum::<i32>() as f64 / self.scores.len() as f64
}
}
fn main() {
let mut students: HashMap<String, Student> = HashMap::new();
// 学生を追加
students.insert("S001".to_string(), Student::new("太郎"));
students.insert("S002".to_string(), Student::new("花子"));
// 成績を追加
if let Some(student) = students.get_mut("S001") {
student.add_score(85);
student.add_score(90);
student.add_score(78);
}
if let Some(student) = students.get_mut("S002") {
student.add_score(92);
student.add_score(88);
}
// 結果を表示
for (id, student) in &students {
println!("{} ({}): 平均 {:.1}点",
student.name, id, student.average());
}
}
まとめ
- 配列
[T; N]は固定長、Vec<T>は可変長 StringはUTF-8文字列、&strは文字列スライスHashMap<K, V>でキーと値のペアHashSet<T>で重複なしの集合iter(),iter_mut(),into_iter()でイテレート- イテレータアダプタで関数型スタイル
次回は構造体について学びます。