У меня есть ArrayList, и мне нужно щелкнуть по кнопке, а затем случайным образом выбрать строку из этого списка и отобразить ее в окне сообщений.
Как мне это сделать?
У меня есть 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 ColectionExtension
{
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> или массивы.
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());
Я использовал этот 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;
}
Мне нужно было больше элемента вместо одного. Итак, я написал это:
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);
Почему бы и нет:
public static T GetRandom<T>(this IEnumerable<T> list)
{
return list.ElementAt(new Random(DateTime.Now.Millisecond).Next(list.Count()));
}