【アルゴリズム】C# 配列要素を漏れ・ダブりなくランダムに取得する方法

この記事では、配列の要素をランダムに漏れ・ダブりなく取得するアルゴリズムについて説明します。

1. この記事で実現すること

たとえば、以下のような配列があったとします。

[1, 5, 8, 13, 35, 67]

この各要素をランダムに漏れ・ダブりなく抽出する方法を考えてみます。

  • 正しい結果

    • [ 35, 8, 13, 67, 5, 1]

    • [ 67, 1, 5, 35, 12, 5]

  • 間違った結果

    • 13 が重複している
    • [ 8, 1, 5, 13, 13, 35, 67]
    • 67が漏れている
    • [ 8, 1, 5, 13, 35]

2. アルゴリズムの概要

1. 0から配列の要素数 - 1 までの整数の乱数を取得します。

以下の場合、要素数は6個です。

[1, 5, 8, 13, 35, 67]   0~5の整数をランダムで選びます。ランダムで「3」が選ばれたとします。

2. ランダム数字に該当する配列の要素を取得します。

以下の場合、3番目の要素は「13」です(配列の1つ目の添え字を0とした場合)

[1, 5, 8, 13, 35, 67]

3. 抽出した配列の要素を、配列から削除します。

今回は「13」が選ばれましたので、「13」を配列から削除します。

削除前は以下のとおりです。

[1, 5, 8, 13, 35, 67]

削除後は、以下のようになります。

[1, 5, 8, 35, 67]

4. 「1.」に戻ります。0から配列の要素数-1までの整数の乱数を取得します。

先ほど、要素「13」が消えましたので、要素数は「5」です。

[1, 5, 8, 35, 67]

ランダムで「0」が選ばれたとします。

5. 「2.」の手順を行います。ランダム数字に該当する配列の要素を取得します。

以下の配列のうち、手順「4.」で取得した乱数0に対応する要素は「1」になります。

[1, 5, 8, 35, 67]

6. 「3.」の手順を行います。抽出した配列の要素を、配列から削除します。

今回は「1」が選ばれましたので、「1」を配列から削除します。

削除前は以下のとおりです。

[1, 5, 8, 35, 67]

削除後は、以下のようになります。

[5, 8, 35, 67]

7. 手順「4.」「5.」「6.」を繰り返します。配列の要素がなくなったら終了です。

3. c#で書くとどうなるか?

c#で書くと、こうなります。


    int[] ArrayItems = { 1, 5, 8, 13, 35, 67 };
    Random rand = new Random();
    int choiceIdx = 0;


    while(ArrayItems.Length > 0)
    {
        choiceIdx = rand.Next(0, ArrayItems.Length);

        Console.WriteLine($"Output: {ArrayItems[choiceIdx]}");

        List<int> ArrayItemsList = new List<int>();
        ArrayItemsList.AddRange(ArrayItems);
        ArrayItemsList.Remove(ArrayItems[choiceIdx]);
        ArrayItems = ArrayItemsList.ToArray();
    }

まず、抽出したい配列を定義します。

    int[] ArrayItems = { 1, 5, 8, 13, 35, 67 };

次にRandomオブジェクトを生成します。

    Random rand = new Random();

ランダム抽出対象の添え字ワークエリアを初期化します。

    int choiceIdx = 0;

抽出対象の配列の要素数が「0より大きい」を満たすまでループします。

    while(ArrayItems.Length > 0)
    {

        ...

    }

ランダム抽出対象の添え字を取得し、配列から要素を取得します。

    choiceIdx = rand.Next(0, ArrayItems.Length);
    Console.WriteLine($"Output: {ArrayItems[choiceIdx]}");

配列から要素を削除します。 配列から要素を直接削除する方法がわかりませんでしたので、一旦リストオブジェクトに変換し、リストから要素を削除して、配列に戻しています。

        List<int> ArrayItemsList = new List<int>();
        ArrayItemsList.AddRange(ArrayItems);
        ArrayItemsList.Remove(ArrayItems[choiceIdx]);
        ArrayItems = ArrayItemsList.ToArray();

以下のように出力されれば、成功です。

Output: 35
Output: 67
Output: 13
Output: 8
Output: 1
Output: 5

以上、アルゴリズムでした。

速攻でメモできる QuickNote リリースしました!

QuickNoteは動作が超軽量でサクサクかけるノートアプリです。一瞬の閃きを逃さずにノートを開き書き始めることができます。 アカウント登録も不要です。お試しあれ!

Excel操作をコマンドで! proBoarderExcel

Excelはマウスで操作するのが基本ですが、マウス操作に疲れてはいませんか? キーボードでExcel操作ができるようになるアプリです。オープンソースで無料です。

積み上げ! Daily Stack リリースしました!

Daily Stack は日々の積み上げを管理するToDoアプリです。過去の積み上げの振り返りだけでなく、ツイート機能もあります。 アカウント登録不要ですぐに使い始めることができます。

ExecNote.app リリースしました!

ExecNoteは、コードが実行できるMarkdownアプリケーションです。Markdownドキュメント内に記載したコードをクリックすると実行ができます。わざわざターミナルを 起動させる必要がありません!無料ですのでもしよければダウンロードをお願いします。

About Me

11年目のシステムエンジニアです。アプリで生活や仕事を改善したい🐱仕事効率化、自動化のアプリ開発が得意です、ご相談ください。 🚀エンタメ系アプリの開発も模索中🐬社内SEや個人アプリ開発者、システムエンジニアになりたい人と繋がりたい🐱