У меня есть ArrayList, и мне нужно иметь возможность щелкнуть по кнопке, а затем случайным образом выбрать строку из этого списка и отобразить ее в окне сообщений.Доступ к случайному элементу в списке
Как бы я это сделал?
У меня есть ArrayList, и мне нужно иметь возможность щелкнуть по кнопке, а затем случайным образом выбрать строку из этого списка и отобразить ее в окне сообщений.Доступ к случайному элементу в списке
Как бы я это сделал?
Создайте экземпляр класса Random
. Обратите внимание, что очень важно не создавать новый экземпляр каждый раз, когда вам нужно случайное число. Вы должны повторно использовать старый экземпляр для достижения однородности в сгенерированных числах. Вы можете иметь static
поля где-то (быть осторожными о вопросах безопасности нити):
static Random rnd = new Random();
Спросите экземпляр Random
, чтобы дать вам случайное число с максимумом числа элементов в ArrayList
:
int r = rnd.Next(list.Count);
Показать строку:
MessageBox.Show((string)list[r]);
Создание Random
экземпляра:
Random rnd = new Random();
Fetch случайную строку:
string s = arraylist[rnd.Next(arraylist.Count)];
Помните, что если вы делаете это часто вы должны повторно использовать Random
объект. Поместите его как статическое поле в класс, чтобы он инициализировался только один раз, а затем доступ к нему.
Я обычно использую этот небольшой набор методов расширения:
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>();
Какова их сложность? ленивая природа IEnumerable означает, что это не O (N)? –
Этот ответ повторно перетасовывает список каждый раз, когда вы выбираете случайное число. Было бы гораздо эффективнее вернуть значение случайного индекса, особенно для больших списков. Используйте это в PickRandom - 'return list [rnd.Next (list.Count)];' – swax
Это не перетасовывает исходный список, но делает его в другом списке, который по-прежнему может быть неэффективным, если список достаточно велик .. – nawfal
Вы можете сделать:
list.OrderBy(x => Guid.NewGuid()).FirstOrDefault()
Красивые. В ASP.NET MVC 4.5, uisng список, мне пришлось изменить это на: list.OrderBy (x => Guid.NewGuid()). FirstOrDefault(); –
В большинстве случаев это не имеет значения, но это, вероятно, намного медленнее, чем использование rnd.Next. OTOH он будет работать на IEnumerable
Не уверен, насколько это случайность. Гиды уникальны, а не случайны. – pomber
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());
Хотя этот фрагмент кода может решить вопрос, [включая объяснение] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода. – gunr2171
Я бы сказал, что параметр 'maxValue' метода' Next' должен быть всего лишь несколькими элементами в списке, а не минусом, потому что согласно документации «* maxValue является ** исключительной верхней границей ** случайное число*". –
Или просто класс расширения, как это:
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>
, или массивы для этой цели.
Массивы в .NET уже реализуют 'IList', поэтому вторая перегрузка не нужна. – Dai
Я использую этот метод расширение на некоторое время:
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;
}
Вы забыли добавить экземпляр Random class – bafsar
мне нужно больше деталь вместо одного. Итак, я написал:
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()));
}
Есть ли хороший способ изменить это, чтобы число не повторялось? Предположим, я хотел перетасовать колоду карт, случайно выбрав один за раз, но, очевидно, не может выбрать одну и ту же карту дважды. – AdamMc331
@ McAdam331 Посмотрите алгоритм Fisher-Yates Shuffle: http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle –
Если это «rnd.Next (list.Count-1)» вместо «rnd» .Next (list.Count) ", чтобы избежать доступа к элементу max, который был бы за пределами индекса, основанного на предположении 0. –