, :
var randomItem = sequence.Skip(rng.Next(sequence.Count())).First();
( ):
var colors = new List<string> { "bronze", "green", "red", "blue", "black", "purple", "brown" };
var rng = new Random();
for (int i = 0; i < 10; ++i)
{
var sequence = colors.Where(c => c.StartsWith("b"));
var randomItem = sequence.Skip(rng.Next(sequence.Count())).First();
Console.WriteLine(randomItem);
}
O (N), , , , .
,
N (O (N)), , , Reservoir Sampling.
, :
.
:
public static T[] RandomlySelectedItems<T>(IEnumerable<T> items, int n, System.Random rng)
{
var result = new T[n];
int index = 0;
int count = 0;
foreach (var item in items)
{
if (index < n)
{
result[count++] = item;
}
else
{
int r = rng.Next(0, index + 1);
if (r < n)
result[r] = item;
}
++index;
}
if (index < n)
throw new ArgumentException("Input sequence too short");
return result;
}
n 1, 1.
( , , , colors.Where(c => c.StartsWith("b") ):
var colors = new List<string> { "green", "red", "blue", "black", "purple" };
var rng = new Random();
for (int i = 0; i < 10; ++i)
Console.WriteLine(RandomlySelectedItems(colors.Where(c => c.StartsWith("b")), 1, rng)[0]);
However, if you want to call this several times, and not just once, you would be better off shuffling the array and accessing the first N elements in the shuffled array. (It's hard to say what your actual usage model will be).