RustのIteratorのmax, max_by_key, max_by の違い
Rust のイテレータに生えているメソッドで、名前が似ているものたちの違いを見てみる max 系しか紹介していないが、min についても同様
※公式ドキュメントの焼き直しです
まとめ
max
単純にイテレータの要素のうち最大のものがほしいときに使う
要素の中で最大のものを返す
イテレータにくっつけて呼ぶだけ
max_by_key
要素を少し加工してから最大値を探す場合に使う
引数に関数を渡し、その返り値で比較がなされる
max_by
要素どうしの比較関数を自分で定義したい場合に利用する
引数には、要素2つを受け取ってOrderingな値を返す関数を渡す
max
イテレータの中で一番大きな要素を返す
イテレータが空のとき None を返し、それ以外は Some(&Item)を返す
一番大きい要素が複数あった場合は、最後の要素を返す
要素には Ord トレイトが実装されている必要がある
code:rs
assert_eq!(v.iter().max(), Some(&3));
let empty: Vec<isize> = Vec::new();
assert_eq!(empty.iter().max(), None);
max_by_key
引数に関数を受け取り、その関数に従って加工された各の中で一番大きいものを探し、それに対応する要素を返す
引数に渡す関数
引数: イテレータの要素
返り値:Ord を実装する値
max と同様に、一番大きい要素が複数あった場合は最後の要素を返す
ユースケース1: 絶対値が最大なものを見つける
code:rs
assert_eq!(a.iter().max_by_key(|x| x.abs()), Some(&-3));
let empty: Vec<isize> = Vec::new();
assert_eq!(empty.iter().max_by_key(|x| x.abs()), None);
ユースケース2:構造体のメンバについて比較する
code:rs
struct MyStruct {
value: isize,
}
fn main() {
let a = vec![
MyStruct { value: 0 },
MyStruct { value: 1 },
MyStruct { value: 2 },
MyStruct { value: 3 },
];
assert_eq!(a.iter().max_by_key(|x| x.value).unwrap().value, 3);
}
max_by
引数に比較関数を受け取る
比較関数:2つの要素を受け取って、Ordering を実装する型の値を返す関数
使ってみる: Person を要素にもつイテレータから、最高齢の人を表す要素を取得する。もし同じ年齢の場合は名前が辞書順で小さくなる要素ほど大きいものとする(※このようなユースケースがあるのかどうかは知らないです)
code:rs
use std::cmp::Ordering;
struct Person {
name: String,
age: u32,
}
fn main() {
let people = vec![
Person {
name: String::from("Alice"),
age: 25,
},
Person {
name: String::from("Bob"),
age: 20,
},
Person {
name: String::from("Charlie"),
age: 25,
},
];
let gratest = people.iter().max_by(|a, b| match a.age.cmp(&b.age) {
Ordering::Equal => b.name.cmp(&a.name), // 辞書順でより若いものが Grater を返すようにする
Ordering::Less => Ordering::Less,
Ordering::Greater => Ordering::Greater,
});
println!("{:#?}", gratest);
}