我有一个数组列表,我需要能够点击一个按钮然后从列表中随机挑选一个字符串并显示在消息框中。

我该怎么做呢?


当前回答

我需要更多的项目,而不仅仅是一个。所以,我写了这个:

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 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>或数组。

我通常使用这个扩展方法的小集合:

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

如果你只有一个数组列表,你可以强制转换它:

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

为什么不:

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

我已经使用这个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;
}

你可以:

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