RandomElement 获取序列的随机元素

List<int> source = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Random r = new Random();
for (int i = 0; i < 100; i++)
{
    Console.WriteLine($"Random: {source.RandomElement(r)}");
}

/// <summary>
/// 从序列中选择随机元素 
/// O(n)序列中每个元素被选择的机会是均等的,而且我们只迭代了一次
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="random">同一个Random</param>
/// <returns></returns>
public static T RandomElement<T>(this IEnumerable<T> source, Random random)
{
	if (source == null)
	{
	    throw new ArgumentNullException("source");
	}
	if (random == null)
	{
	    throw new ArgumentNullException("random");
	}
	ICollection collection = source as ICollection;
	if (collection != null)
	{
	    int count = collection.Count;
	    if (count == 0)
	    {
	        throw new InvalidOperationException("Sequence was empty.");
	    }
	    int indx = random.Next(count);
	    return source.ElementAt(indx);
	}
	using (IEnumerator<T> iter = source.GetEnumerator())
	{
	    if (!iter.MoveNext())
	    {
	        throw new InvalidOperationException("Sequence was empty.");
	    }
	    int cntSoFar = 1;
	    T current = iter.Current;
	    while (iter.MoveNext())
	    {
	        cntSoFar++;
	        if (random.Next(cntSoFar) == 0)
	        {
	            current = iter.Current;
	        }
	    }
	    return current;
	}
}
posted @ 2019-12-02 16:42  wesson2019  阅读(576)  评论(0编辑  收藏  举报