web-dev-qa-db-ja.com

選択基準が等しい場合に、オプションのセットの1つをランダムに選択するパターンはありますか?

いくつかのオプションから選択したいのですが、選択に使用している基準が偶然に等しい場合は、ランダムに1つを選択します(合理的にそうなので、任意ではなく、毎回等確率です)。これはネストされたifで簡単に実行できますが、かなり醜くなり、コードを複製することになります。

単純化されたサンプルケース(明確でない場合)。

extern crate Rand;

fn main() {
    let a = 5;
    let b = 5;

    if a > b {
        println!("Do the thing where a is bigger");
    } else if b < a {
        println!("Do the thing where b is bigger");
    } else { 
        if Rand::random::<bool>() {
            // I don't want to duplicate the code here!
            println!("Do the thing where a is bigger");
        } else {
            // Or here!
            println!("Do the thing where b is bigger");
        }
    }

}

錆の遊び場

コードを複製する必要がない、これを行うより良い方法はありますか?この単純化された例では、2つの可能性から選択しているだけですが、実際にはより長いリストになる可能性があります。 (最高のabcdに基づいて行動するのはどうですか?2、3、または4方法ネクタイ?)

私はたまたまRustを学んでいるので、クールで優れた言語機能がある場合は、可能であれば一般的なケースにも興味があります。

3
mattdm

最初の一般的な方法は、関数分解を使用して重複を減らすことです。これは、複雑な関数をより単純で潜在的に再利用可能な部分に分解することを意味します。次に、コードは関数呼び出しのみを複製します。

fn do_a() {
    println!("Do the thing where a is bigger");
}
fn do_b() {
    println!("Do the thing where b is bigger");
}
fn main() {
    ...

    if a > b {
        do_a();
    } else if b < a {
        do_b();
    } else { 
        if Rand::random::<bool>() {
            do_a();
        } else {
            do_b();
        }
    }
}

より効果的な方法は、コードをリファクタリングすることです条件式の統合; Rustは知りませんので、言語エラーは許しませんが、次のようなものになります。

fn main() {
    let a = 5;
    let b = 5;

    let agb = if a==b { Rand::random::<bool>() } else { a>b };
    if agb {
        do_a();
    } else {
        do_b();
    }
}
5
Christophe