ArrayListがあり、ボタンをクリックしてそのリストからランダムに文字列を取り出してメッセージボックスに表示できるようにする必要があります。
これをどのようにして行うのでしょうか。
どこかにRandom
クラスのインスタンスを作成します。乱数が必要になるたびに新しいインスタンスを作成しないことが非常に重要です。生成された数の統一を図るために、古いインスタンスを再利用する必要があります。あなたはどこかにstatic
フィールドを持つことができます(スレッドの安全性の問題に注意してください):
static Random rnd = new Random();
Random
インスタンスに、ArrayList
内の最大項目数の乱数を与えるように依頼します。
int r = rnd.Next(list.Count);
文字列を表示します。
MessageBox.Show((string)list[r]);
私は通常、この小さな拡張メソッドのコレクションを使います。
public static class EnumerableExtension
{
public static T PickRandom<T>(this IEnumerable<T> source)
{
return source.PickRandom(1).Single();
}
public static IEnumerable<T> PickRandom<T>(this IEnumerable<T> source, int count)
{
return source.Shuffle().Take(count);
}
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
return source.OrderBy(x => Guid.NewGuid());
}
}
強く型付けされたリストのために、これはあなたが書くことを可能にするでしょう:
var strings = new List<string>();
var randomString = strings.PickRandom();
あなたが持っているのがArrayListだけなら、あなたはそれをキャストすることができます:
var strings = myArrayList.Cast<string>();
できるよ:
list.OrderBy(x => Guid.NewGuid()).FirstOrDefault()
Random
インスタンスを作成します。
Random rnd = new Random();
ランダムな文字列を取得します:
string s = arraylist[rnd.Next(arraylist.Count)];
ただし、これを頻繁に行う場合はRandom
オブジェクトを再利用する必要があります。それをクラス内の静的フィールドとして置くので、一度だけ初期化されてからアクセスされます。
またはこのような単純な拡張クラス:
public static class CollectionExtension
{
private static Random rng = new Random();
public static T RandomElement<T>(this IList<T> list)
{
return list[rng.Next(list.Count)];
}
public static T RandomElement<T>(this T[] array)
{
return array[rng.Next(array.Length)];
}
}
それからちょうど呼んでください:
myList.RandomElement();
配列にも使えます。
OrderBy()
を呼び出すのは避けましょう。コレクションが大きいとコストがかかる可能性があるからです。この目的のためにList<T>
または配列のようなインデックス付きのコレクションを使用してください。
何故なの:
public static T GetRandom<T>(this IEnumerable<T> list)
{
return list.ElementAt(new Random(DateTime.Now.Millisecond).Next(list.Count()));
}
ArrayList ar = new ArrayList();
ar.Add(1);
ar.Add(5);
ar.Add(25);
ar.Add(37);
ar.Add(6);
ar.Add(11);
ar.Add(35);
Random r = new Random();
int index = r.Next(0,ar.Count-1);
MessageBox.Show(ar[index].ToString());
1つだけではなくもっと多くのアイテムが必要でした。だから、私はこれを書いた:
public static TList GetSelectedRandom<TList>(this TList list, int count)
where TList : IList, new()
{
var r = new Random();
var rList = new TList();
while (count > 0 && list.Count > 0)
{
var n = r.Next(0, list.Count);
var e = list[n];
rList.Add(e);
list.RemoveAt(n);
count--;
}
return rList;
}
これを使えば、このようにランダムに好きなだけ要素を得ることができます。
var _allItems = new List<TModel>()
{
// ...
// ...
// ...
}
var randomItemList = _allItems.GetSelectedRandom(10);
私はしばらくこのExtensionMethodを使っています:
public static IEnumerable<T> GetRandom<T>(this IEnumerable<T> list, int count)
{
if (count <= 0)
yield break;
var r = new Random();
int limit = (count * 10);
foreach (var item in list.OrderBy(x => r.Next(0, limit)).Take(count))
yield return item;
}