Да, я верю в это.
Когда вы впервые сталкиваетесь с соответствующим элементом, вы определенно выбираете его. В следующий раз вы выбираете новое значение с вероятностью 1/2, так что каждый из двух элементов имеет равные шансы. В следующий раз вы выбираете новое значение с вероятностью 1/3, оставляя каждый из остальных элементов с вероятностью 1/2 * 2/3 = 1/3.
Я пытаюсь найти статью об этой стратегии в Википедии, но пока что не получается ...
Обратите внимание, что в общем случае вы просто выбираете случайную выборку из последовательности неизвестной длины. Ваша последовательность генерируется путем взятия начальной последовательности и ее фильтрации, но алгоритм вообще не требует этой части.
Я думал, что для этого у меня есть оператор LINQ в MoreLINQ, но я не могу найти его в хранилище ... РЕДАКТИРОВАТЬ: К счастью, он все еще существует с этого ответа :
public static T RandomElement<T>(this IEnumerable<T> source,
Random rng)
{
T current = default(T);
int count = 0;
foreach (T element in source)
{
count++;
if (rng.Next(count) == 0)
{
current = element;
}
}
if (count == 0)
{
throw new InvalidOperationException("Sequence was empty");
}
return current;
}