Как получить доступ к случайному элементу в списке? - PullRequest
207 голосов
/ 07 января 2010

У меня есть ArrayList, и мне нужно иметь возможность нажать кнопку, а затем случайным образом выбрать строку из этого списка и отобразить ее в окне сообщения.

Как бы я поступил так?

Ответы [ 10 ]

371 голосов
/ 07 января 2010
  1. Создать где-нибудь экземпляр класса Random. Обратите внимание, что очень важно не создавать новый экземпляр каждый раз, когда вам нужно случайное число. Вы должны повторно использовать старый экземпляр для достижения единообразия в генерируемых числах. Где-то может быть поле static (будьте осторожны с вопросами безопасности потоков):

    static Random rnd = new Random();
    
  2. Попросите экземпляр Random дать вам случайное число с максимальным количеством элементов в ArrayList:

    int r = rnd.Next(list.Count);
    
  3. Показать строку:

    MessageBox.Show((string)list[r]);
    
127 голосов
/ 07 января 2010

Я обычно использую эту небольшую коллекцию методов расширения:

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>();
84 голосов
/ 07 января 2010

Вы можете сделать:

list.OrderBy(x => Guid.NewGuid()).FirstOrDefault()
20 голосов
/ 07 января 2010

Создать экземпляр Random:

Random rnd = new Random();

Получить случайную строку:

string s = arraylist[rnd.Next(arraylist.Count)];

Помните, что если вы делаете это часто, вам следует повторно использовать объект Random. Поместите его как статическое поле в классе, чтобы оно инициализировалось только один раз, а затем получите к нему доступ.

12 голосов
/ 15 апреля 2016

Или простой класс расширения, например:

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> или массивы.

3 голосов
/ 17 мая 2017

Почему бы и нет:

public static T GetRandom<T>(this IEnumerable<T> list)
{
   return list.ElementAt(new Random(DateTime.Now.Millisecond).Next(list.Count()));
}
2 голосов
/ 06 ноября 2014
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());
0 голосов
/ 20 сентября 2018

Почему бы и нет [2]:

public static T GetRandom<T>(this List<T> list)
{
     return list[(int)(DateTime.Now.Ticks%list.Count)];
}
0 голосов
/ 09 марта 2017

Мне нужно было больше предметов вместо одного. Итак, я написал это:

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); 
0 голосов
/ 27 августа 2016

Я давно использую этот 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;
}
...