この記事では、配列の要素をランダムに漏れ・ダブりなく取得するアルゴリズムについて説明します。
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
以上、アルゴリズムでした。
おすすめ本 c#コードレシピ集
c#コードレシピ集は、「文字列を大文字あるいは小文字に変換したい」や「Taskをキャンセルしたい」など逆引き的にコードの書き方を調べられるレシピ集です。
2021年8月に発売された本で、全部で385個のレシピが収録されています。
ジャンルは日付処理やLINQ、並列処理と非同期処理など幅広く記載されています。
Kindle対応ですので、まずはサンプルをダウンロードして何が書かれているか確認してはいかがでしょうか。
コメント