Подтвердить что ты не робот

Доступ к случайному элементу в списке

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

Как мне это сделать?

4b9b3361

Ответ 1

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

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

    int r = rnd.Next(list.Count);
    
  • Отобразите строку:

    MessageBox.Show((string)list[r]);
    

Ответ 2

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

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>();

Ответ 3

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

list.OrderBy(x => Guid.NewGuid()).FirstOrDefault()

Ответ 4

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

Random rnd = new Random();

Выберите случайную строку:

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

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

Ответ 5

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

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

Ответ 6

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());

Ответ 7

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

Ответ 8

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

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); 

Ответ 9

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

public static T GetRandom<T>(this IEnumerable<T> list)
{
   return list.ElementAt(new Random(DateTime.Now.Millisecond).Next(list.Count()));
}