Sibainu Relax Room

愛犬の柴犬とともに過ごす部屋

RUST 構造体の大小比較

お!頑張っているなという顔している柴犬です。

ここ数日、というか2週間ほど RUST のトレイト周辺の理解に苦しんでいましたが、ちょっと光が見えてきました。

トレイトのソースを読むのが一番いいようです。

そのお陰、今回の投稿ができました。

概要

構造体の大小比較したい場合、条件次第で次のコードで可能です。

copy

#[derive(PartialEq, PartialOrd)]
struct Sline {
    f0: u32,
    f1: String,
    f2: String,
}

// 構造体のメソッド
impl Sline {
    fn new(f0: u32, f1: &str, f2: &str) -> Self {
        Self {
            f0: 0,
            f1: f1.to_string(),
            f2: f2.to_string(),
        }
    }
}

fn main() {
    let s1 = Sline::new(1, "0234","15");
    let s2 = Sline::new(5, "1234","13");
    println!("{}", s1 > s2);
}

上のコードを Rust Playground で実行すると次のようになります。

しかし、大小の判定は構造体の要素順でしかならないなど制約があるため、これを任意にしてできるようにしてみました。

考えたコード

構造体の要素 f0 を無視して大小を比較するようにしてみました。

copy

use std::cmp::Ordering;

// 構造体の定義
#[derive(Eq)]
struct Sline {
    f0: u32,
    f1: String,
    f2: String,
}

// 構造体のメソッド
impl Sline {
    fn new(f0: u32, f1: &str, f2: &str) -> Self {
        Self {
            f0: 0,
            f1: f1.to_string(),
            f2: f2.to_string(),
        }
    }
}

impl Ord for Sline {
    fn cmp(&self, other: &Self) -> Ordering {
        match (self.f1.cmp(&other.f1), self.f2.cmp(&other.f2)) {
            (Ordering::Greater, _) => Ordering::Greater,
            (Ordering::Equal, Ordering::Greater) => Ordering::Greater,
            (Ordering::Equal, Ordering::Equal) => Ordering::Equal,
            _ => Ordering::Less,
        }
    }
}

impl PartialOrd for Sline {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for Sline {
    fn eq(&self, other: &Self) -> bool {
        self.f1 == other.f1 && self.f2 == other.f2
    }
}

fn main() {
    let s1 = Sline::new(1, "1234","12");
    let s2 = Sline::new(5, "1234","11");
    println!("{}", s1 > s2);
}

上のコードを Rust Playground で実行すると次のようになります。

要素 f0 を無視して大小を比較した結果になっています。

Ordering について

Ordering は、2 つの値を比較した結果を表す列挙型です。

pub enum Ordering {
    Less,
    Equal,
    Greater,
}

let result = 1.cmp(&2);
result には Ordering::Less が格納されます。

let result = 1.cmp(&1);
result には Ordering::Equal が格納されます。

let result = 2.cmp(&1);
result には Ordering::Greater が格納されます。

変形

次の部分をいじれば要素の選択、比較順、昇順、降順を任意に変えれそうです。

copy

impl Ord for Sline {
    fn cmp(&self, other: &Self) -> Ordering {
        match (self.f1.cmp(&other.f1), self.f2.cmp(&other.f2)) {
            (Ordering::Greater, _) => Ordering::Greater,
            (Ordering::Equal, Ordering::Greater) => Ordering::Greater,
            (Ordering::Equal, Ordering::Equal) => Ordering::Equal,
            _ => Ordering::Less,
        }
    }
}

// 略

impl PartialEq for Sline {
    fn eq(&self, other: &Self) -> bool {
        self.f1 == other.f1 && self.f2 == other.f2
    }
}