\

【アルゴリズム】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#で書くと、こうなります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

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();
}

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

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

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

1
Random rand = new Random();

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

1
int choiceIdx = 0;

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

1
2
3
4
5
6
while(ArrayItems.Length > 0)
{

...

}

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

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

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

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

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

1
2
3
4
5
6
Output: 35
Output: 67
Output: 13
Output: 8
Output: 1
Output: 5

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

コメントシステムを導入しました!コメント頂けると嬉しすぎて、光の速さで返信します(●´ω`●)

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

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

About Me

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