Re: Random Extension
- From: "Alberto Poblacion" <earthling-quitaestoparacontestar@xxxxxxxxxxxxx>
- Date: Tue, 17 Nov 2009 09:53:10 +0100
"Göran Andersson" <guffa@xxxxxxxxx> wrote in message news:uguXouyZKHA.4932@xxxxxxxxxxxxxxxxxxxxxxx
I just happen to have an extension lying around that does this in a more efficient way:
public static T PickRandomOne<T>(this IEnumerable<T> list, Random rnd) {
T picked = default(T);
int cnt = 0;
foreach (T item in list) {
if (rnd.Next(++cnt) == 0) {
picked = item;
}
}
return picked;
}
It loops through the items and check for each item if it should keep it or not. As it doesn't have to know how many items there are, it only has to loop through the items once.
However, note that your method does not return all the elements in the collection with equal probability. The first element has a 50% chance of being picked, the second one chance in 6, the third a smaller number and so on. And there's no guarantee that any of the members will be chosen at all, so default(T) could be returned even if the collection is not empty.
In order to achieve an equal probability, I think that the only way to do it requires to know the number of elements in advance, and if you only have an IEnumerable interface, this requires looping through the entire collection before being able to choose the "random" item to be returned.
Certainly, the Original Poster's code calls Count() twice, which can be avoided, but we still need one Count() plus one ElementAt(), which requires looping through the entire collection by average one and a half times.
.
- Follow-Ups:
- Re: Random Extension
- From: Göran Andersson
- Re: Random Extension
- References:
- Random Extension
- From: shapper
- Re: Random Extension
- From: Göran Andersson
- Random Extension
- Prev by Date: Desktop Application Data Access Layer
- Next by Date: Re: ref parameter
- Previous by thread: Re: Random Extension
- Next by thread: Re: Random Extension
- Index(es):
Relevant Pages
|