web-dev-qa-db-fra.com

Comment accéder aux éléments aléatoires de la liste?

J'ai une liste de tableaux et je dois pouvoir cliquer sur un bouton, puis sélectionner au hasard une chaîne de cette liste et l'afficher dans une boîte de message.

Comment pourrais-je m'y prendre?

214
jay_t55
  1. Créez une instance de Random class quelque part. Notez qu'il est très important de ne pas créer une nouvelle instance à chaque fois que vous avez besoin d'un nombre aléatoire. Vous devez réutiliser l'ancienne instance pour uniformiser les nombres générés. Vous pouvez avoir un champ static quelque part (faites attention aux problèmes de sécurité des threads):

    static Random rnd = new Random();
    
  2. Demandez à l'instance Random de vous donner un nombre aléatoire avec le nombre maximal d'éléments dans la ArrayList:

    int r = rnd.Next(list.Count);
    
  3. Afficher la chaîne:

    MessageBox.Show((string)list[r]);
    
378
Mehrdad Afshari

J'utilise habituellement cette petite collection de méthodes d'extension:

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

Pour une liste fortement typée, cela vous permettrait d'écrire:

var strings = new List<string>();
var randomString = strings.PickRandom();

Si tout ce que vous avez est une ArrayList, vous pouvez le lancer:

var strings = myArrayList.Cast<string>();
129
Mark Seemann

Tu peux faire:

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

Créez une instance Random:

Random rnd = new Random();

Récupérer une chaîne aléatoire:

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

Rappelez-vous cependant que si vous le faites fréquemment, vous devez réutiliser l'objet Random. Mettez-le comme un champ statique dans la classe pour qu'il ne soit initialisé qu'une fois, puis y accéder.

20
Joey

Ou une classe d'extension simple comme celle-ci:

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

Alors appelez simplement:

myList.RandomElement();

Fonctionne aussi pour les tableaux.

J'éviterais d'appeler OrderBy() car cela peut coûter cher pour de plus grandes collections. Utilisez des collections indexées comme List<T> ou des tableaux à cette fin.

13
Dave_cz

Pourquoi pas:

public static T GetRandom<T>(this IEnumerable<T> list)
{
   return list.ElementAt(new Random(DateTime.Now.Millisecond).Next(list.Count()));
}
3
Lucas
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());
2
Rajesh Varma

J'avais besoin de plus d'articles au lieu d'un seul. Donc, j'ai écrit ceci:

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

Avec cela, vous pouvez obtenir autant d'éléments que vous le souhaitez au hasard:

var _allItems = new List<TModel>()
{
    // ...
    // ...
    // ...
}

var randomItemList = _allItems.GetSelectedRandom(10); 
0
bafsar

J'utilise cette extensionMethod depuis un moment:

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;
}
0
Carlos Toledo