EDIT: я только что заметил, что это LINQ to SQL, а не LINQ to Objects. Используйте код Марка, чтобы получить базу данных, чтобы сделать это для вас. Я оставил этот ответ здесь как потенциальный интерес для LINQ to Objects.
Как ни странно, вам не нужно получать счет. Однако вам нужно выбрать каждый элемент, если вы не получите счетчик.
Что вы можете сделать, так это сохранить представление о «текущем» значении и текущем количестве. Когда вы выбираете следующее значение, возьмите случайное число и замените «текущий» на «новый» с вероятностью 1 / n, где n - это число.
Таким образом, когда вы читаете первое значение, вы всегда делаете это «текущее» значение. Когда вы читаете второе значение, вы можете сделать это текущее значение (вероятность 1/2). Когда вы читаете третье значение, вы можете сделать это текущее значение (вероятность 1/3) и т. Д. Когда у вас заканчиваются данные, текущее значение является случайным из всех, которые вы читать с равномерной вероятностью.
Чтобы применить это к условию, просто игнорируйте все, что не соответствует условию. Самый простой способ сделать это - рассмотреть только «совпадающую» последовательность для начала, применив сначала условие Where.
Вот быстрая реализация. Я думаю все в порядке ...
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;
}